diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp --- a/app/mainwindow.cpp +++ b/app/mainwindow.cpp @@ -300,6 +300,10 @@ if (dialog.data()->compressionLevel() > -1) { m_openArgs.metaData()[QStringLiteral("compressionLevel")] = QString::number(dialog.data()->compressionLevel()); } + if (dialog.data()->volumeSize() > 0) { + qCDebug(ARK) << "Setting volume size:" << QString::number(dialog.data()->volumeSize()); + m_openArgs.metaData()[QStringLiteral("volumeSize")] = QString::number(dialog.data()->volumeSize()); + } m_openArgs.metaData()[QStringLiteral("encryptionPassword")] = password; if (dialog.data()->isHeaderEncryptionEnabled()) { diff --git a/autotests/plugins/cli7zplugin/cli7ztest.cpp b/autotests/plugins/cli7zplugin/cli7ztest.cpp --- a/autotests/plugins/cli7zplugin/cli7ztest.cpp +++ b/autotests/plugins/cli7zplugin/cli7ztest.cpp @@ -305,7 +305,7 @@ QFETCH(bool, encryptHeader); QFETCH(int, compressionLevel); - QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel); + QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel, 0); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); diff --git a/autotests/plugins/clirarplugin/clirartest.cpp b/autotests/plugins/clirarplugin/clirartest.cpp --- a/autotests/plugins/clirarplugin/clirartest.cpp +++ b/autotests/plugins/clirarplugin/clirartest.cpp @@ -334,7 +334,7 @@ QFETCH(bool, encryptHeader); QFETCH(int, compressionLevel); - QStringList replacedArgs = rarPlugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel); + QStringList replacedArgs = rarPlugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel, 0); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); diff --git a/autotests/plugins/clizipplugin/cliziptest.cpp b/autotests/plugins/clizipplugin/cliziptest.cpp --- a/autotests/plugins/clizipplugin/cliziptest.cpp +++ b/autotests/plugins/clizipplugin/cliziptest.cpp @@ -106,7 +106,7 @@ QFETCH(QString, password); QFETCH(int, compressionLevel); - QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, false, compressionLevel); + QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, false, compressionLevel, 0); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); diff --git a/kerfuffle/adddialog.cpp b/kerfuffle/adddialog.cpp --- a/kerfuffle/adddialog.cpp +++ b/kerfuffle/adddialog.cpp @@ -88,6 +88,7 @@ CompressionOptions AddDialog::compressionOptions() const { + qCDebug(ARK) << "Returning with options:" << m_compOptions; return m_compOptions; } @@ -100,6 +101,7 @@ CompressionOptionsWidget *optionsWidget = new CompressionOptionsWidget(optionsDialog, m_compOptions); optionsWidget->setMimeType(m_mimeType); optionsWidget->setEncryptionVisible(false); + optionsWidget->collapsibleMultiVolume->setVisible(false); optionsWidget->collapsibleCompression->expand(); vlayout->addWidget(optionsWidget); diff --git a/kerfuffle/archive_kerfuffle.h b/kerfuffle/archive_kerfuffle.h --- a/kerfuffle/archive_kerfuffle.h +++ b/kerfuffle/archive_kerfuffle.h @@ -151,7 +151,7 @@ Q_PROPERTY(QMimeType mimeType READ mimeType CONSTANT) Q_PROPERTY(bool isReadOnly READ isReadOnly CONSTANT) Q_PROPERTY(bool isSingleFolderArchive READ isSingleFolderArchive) - Q_PROPERTY(bool isMultiVolume READ isMultiVolume) + Q_PROPERTY(bool isMultiVolume READ isMultiVolume WRITE setMultiVolume) Q_PROPERTY(bool numberOfVolumes READ numberOfVolumes) Q_PROPERTY(EncryptionType encryptionType READ encryptionType) Q_PROPERTY(qulonglong numberOfFiles READ numberOfFiles) @@ -176,8 +176,9 @@ QMimeType mimeType(); bool isReadOnly() const; bool isSingleFolderArchive(); - bool hasComment() const; bool isMultiVolume() const; + void setMultiVolume(bool value); + bool hasComment() const; int numberOfVolumes() const; EncryptionType encryptionType(); QString password() const; @@ -188,6 +189,7 @@ QString subfolderName(); void setCompressionOptions(const CompressionOptions &opts); CompressionOptions compressionOptions() const; + QString multiVolumeName() const; static Archive *create(const QString &fileName, QObject *parent = 0); static Archive *create(const QString &fileName, const QString &fixedMimeType, QObject *parent = 0); @@ -257,6 +259,7 @@ bool m_hasBeenListed; bool m_isReadOnly; bool m_isSingleFolderArchive; + bool m_isMultiVolume; QString m_subfolderName; qulonglong m_extractedFilesSize; diff --git a/kerfuffle/archive_kerfuffle.cpp b/kerfuffle/archive_kerfuffle.cpp --- a/kerfuffle/archive_kerfuffle.cpp +++ b/kerfuffle/archive_kerfuffle.cpp @@ -126,6 +126,7 @@ , m_hasBeenListed(false) , m_isReadOnly(isReadOnly) , m_isSingleFolderArchive(false) + , m_isMultiVolume(false) , m_extractedFilesSize(0) , m_error(NoError) , m_encryptionType(Unencrypted) @@ -232,6 +233,11 @@ return m_iface->isMultiVolume(); } +void Archive::setMultiVolume(bool value) +{ + m_iface->setMultiVolume(value); +} + int Archive::numberOfVolumes() const { return m_iface->numberOfVolumes(); @@ -495,4 +501,9 @@ return m_compOptions; } +QString Archive::multiVolumeName() const +{ + return m_iface->multiVolumeName(); +} + } // namespace Kerfuffle diff --git a/kerfuffle/archiveformat.h b/kerfuffle/archiveformat.h --- a/kerfuffle/archiveformat.h +++ b/kerfuffle/archiveformat.h @@ -43,7 +43,8 @@ int maxCompLevel, int defaultCompLevel, bool supportsWriteComment, - bool supportsTesting); + bool supportsTesting, + bool suppportsMultiVolume); /** * @return The archive format of the given @p mimeType, according to the given @p metadata. @@ -65,6 +66,7 @@ int defaultCompressionLevel() const; bool supportsWriteComment() const; bool supportsTesting() const; + bool supportsMultiVolume() const; private: QMimeType m_mimeType; @@ -74,6 +76,7 @@ int m_defaultCompressionLevel; bool m_supportsWriteComment; bool m_supportsTesting; + bool m_supportsMultiVolume; }; } diff --git a/kerfuffle/archiveformat.cpp b/kerfuffle/archiveformat.cpp --- a/kerfuffle/archiveformat.cpp +++ b/kerfuffle/archiveformat.cpp @@ -39,14 +39,16 @@ int maxCompLevel, int defaultCompLevel, bool supportsWriteComment, - bool supportsTesting) : + bool supportsTesting, + bool supportsMultiVolume) : m_mimeType(mimeType), m_encryptionType(encryptionType), m_minCompressionLevel(minCompLevel), m_maxCompressionLevel(maxCompLevel), m_defaultCompressionLevel(defaultCompLevel), m_supportsWriteComment(supportsWriteComment), - m_supportsTesting(supportsTesting) + m_supportsTesting(supportsTesting), + m_supportsMultiVolume(supportsMultiVolume) { } @@ -66,6 +68,7 @@ bool supportsWriteComment = formatProps[QStringLiteral("SupportsWriteComment")].toBool(); bool supportsTesting = formatProps[QStringLiteral("SupportsTesting")].toBool(); + bool supportsMultiVolume = formatProps[QStringLiteral("SupportsMultiVolume")].toBool(); Archive::EncryptionType encType = Archive::Unencrypted; if (formatProps[QStringLiteral("HeaderEncryption")].toBool()) { @@ -74,7 +77,7 @@ encType = Archive::Encrypted; } - return ArchiveFormat(mimeType, encType, minCompLevel, maxCompLevel, defaultCompLevel, supportsWriteComment, supportsTesting); + return ArchiveFormat(mimeType, encType, minCompLevel, maxCompLevel, defaultCompLevel, supportsWriteComment, supportsTesting, supportsMultiVolume); } return ArchiveFormat(); @@ -115,4 +118,9 @@ return m_supportsTesting; } +bool ArchiveFormat::supportsMultiVolume() const +{ + return m_supportsMultiVolume; +} + } diff --git a/kerfuffle/archiveinterface.h b/kerfuffle/archiveinterface.h --- a/kerfuffle/archiveinterface.h +++ b/kerfuffle/archiveinterface.h @@ -106,6 +106,8 @@ virtual bool doResume(); bool isHeaderEncryptionEnabled() const; + virtual QString multiVolumeName() const; + void setMultiVolume(bool value); signals: void cancelled(); @@ -129,7 +131,6 @@ void setCorrupt(bool isCorrupt); bool isCorrupt() const; QString m_comment; - bool m_isMultiVolume; int m_numberOfVolumes; private: @@ -138,6 +139,7 @@ bool m_waitForFinishedSignal; bool m_isHeaderEncryptionEnabled; bool m_isCorrupt; + bool m_isMultiVolume; }; class KERFUFFLE_EXPORT ReadWriteArchiveInterface: public ReadOnlyArchiveInterface diff --git a/kerfuffle/archiveinterface.cpp b/kerfuffle/archiveinterface.cpp --- a/kerfuffle/archiveinterface.cpp +++ b/kerfuffle/archiveinterface.cpp @@ -120,11 +120,21 @@ return m_isMultiVolume; } +void ReadOnlyArchiveInterface::setMultiVolume(bool value) +{ + m_isMultiVolume = value; +} + int ReadOnlyArchiveInterface::numberOfVolumes() const { return m_numberOfVolumes; } +QString ReadOnlyArchiveInterface::multiVolumeName() const +{ + return filename(); +} + ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList & args) : ReadOnlyArchiveInterface(parent, args) { diff --git a/kerfuffle/cliinterface.h b/kerfuffle/cliinterface.h --- a/kerfuffle/cliinterface.h +++ b/kerfuffle/cliinterface.h @@ -263,7 +263,9 @@ CommentSwitch, TestProgram, TestArgs, - TestPassedPattern + TestPassedPattern, + MultiVolumeSwitch, + MultiVolumeSuffix }; typedef QHash ParameterList; @@ -310,7 +312,7 @@ QStringList substituteListVariables(const QStringList &listArgs, const QString &password); QStringList substituteCopyVariables(const QStringList &extractArgs, const QVariantList &files, bool preservePaths, const QString &password); - QStringList substituteAddVariables(const QStringList &addArgs, const QStringList &files, const QString &password, bool encryptHeader, int compLevel); + QStringList substituteAddVariables(const QStringList &addArgs, const QStringList &files, const QString &password, bool encryptHeader, int compLevel, ulong volumeSize); QStringList substituteDeleteVariables(const QStringList &deleteArgs, const QVariantList &files, const QString &password); QStringList substituteCommentVariables(const QStringList &commentArgs, const QString &commentFile); QStringList substituteTestVariables(const QStringList &testArgs, const QString &password); @@ -335,11 +337,15 @@ */ QString compressionLevelSwitch(int level) const; + QString multiVolumeSwitch(ulong volumeSize) const; + /** * @return The list of selected files to extract. */ QStringList copyFilesList(const QVariantList& files) const; + QString multiVolumeName() const; + protected: virtual void handleLine(const QString& line); diff --git a/kerfuffle/cliinterface.cpp b/kerfuffle/cliinterface.cpp --- a/kerfuffle/cliinterface.cpp +++ b/kerfuffle/cliinterface.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -182,12 +183,14 @@ } int compLevel = options.value(QStringLiteral("CompressionLevel"), -1).toInt(); + ulong volumeSize = options.value(QStringLiteral("VolumeSize"), 0).toULongLong(); const auto args = substituteAddVariables(m_param.value(AddArgs).toStringList(), files, password(), isHeaderEncryptionEnabled(), - compLevel); + compLevel, + volumeSize); if (!runProcess(m_param.value(AddProgram).toStringList(), args)) { return false; @@ -303,7 +306,7 @@ } } - if (m_operationMode == Add) { + if (m_operationMode == Add && !isMultiVolume()) { list(); } else if (m_operationMode == List && isCorrupt()) { Kerfuffle::LoadCorruptQuery query(filename()); @@ -635,7 +638,7 @@ return args; } -QStringList CliInterface::substituteAddVariables(const QStringList &addArgs, const QStringList &files, const QString &password, bool encryptHeader, int compLevel) +QStringList CliInterface::substituteAddVariables(const QStringList &addArgs, const QStringList &files, const QString &password, bool encryptHeader, int compLevel, ulong volumeSize) { // Required if we call this function from unit tests. cacheParameterList(); @@ -659,6 +662,11 @@ continue; } + if (arg == QLatin1String("$MultiVolumeSwitch")) { + args << multiVolumeSwitch(volumeSize); + continue; + } + if (arg == QLatin1String("$Files")) { args << files; continue; @@ -832,6 +840,24 @@ return compLevelSwitch; } +QString CliInterface::multiVolumeSwitch(ulong volumeSize) const +{ + // The maximum value we allow in the QDoubleSpinBox is 1000MB. Converted to + // KB this is 1024000. + if (volumeSize <= 0 || volumeSize > 1024000) { + return QString(); + } + + Q_ASSERT(m_param.contains(MultiVolumeSwitch)); + + QString multiVolumeSwitch = m_param.value(MultiVolumeSwitch).toString(); + Q_ASSERT(!multiVolumeSwitch.isEmpty()); + + multiVolumeSwitch.replace(QLatin1String("$VolumeSize"), QString::number(volumeSize)); + + return multiVolumeSwitch; +} + QStringList CliInterface::copyFilesList(const QVariantList& files) const { QStringList filesList; @@ -1261,4 +1287,20 @@ return true; } +QString CliInterface::multiVolumeName() const +{ + QString oldSuffix = QMimeDatabase().suffixForFileName(filename()); + QString name; + + foreach (const QString &multiSuffix, m_param.value(MultiVolumeSuffix).toStringList()) { + QString newSuffix = multiSuffix; + newSuffix.replace(QStringLiteral("$Suffix"), oldSuffix); + name = filename().remove(oldSuffix).append(newSuffix); + if (QFileInfo(name).exists()) { + break; + } + } + return name; +} + } diff --git a/kerfuffle/compressionoptionswidget.h b/kerfuffle/compressionoptionswidget.h --- a/kerfuffle/compressionoptionswidget.h +++ b/kerfuffle/compressionoptionswidget.h @@ -45,6 +45,7 @@ explicit CompressionOptionsWidget(QWidget *parent = Q_NULLPTR, const CompressionOptions &opts = QHash()); int compressionLevel() const; + ulong volumeSize() const; QString password() const; CompressionOptions commpressionOptions() const; bool isEncryptionAvailable() const; @@ -61,6 +62,9 @@ QMimeType m_mimetype; CompressionOptions m_opts; + +private slots: + void slotMultiVolumeChecked(int state); }; } diff --git a/kerfuffle/compressionoptionswidget.cpp b/kerfuffle/compressionoptionswidget.cpp --- a/kerfuffle/compressionoptionswidget.cpp +++ b/kerfuffle/compressionoptionswidget.cpp @@ -47,12 +47,24 @@ KColorScheme colorScheme(QPalette::Active, KColorScheme::View); pwdWidget->setBackgroundWarningColor(colorScheme.background(KColorScheme::NegativeBackground).color()); pwdWidget->setPasswordStrengthMeterVisible(false); + + connect(multiVolumeCheckbox, &QCheckBox::stateChanged, this, &CompressionOptionsWidget::slotMultiVolumeChecked); + + if (m_opts.contains(QStringLiteral("VolumeSize"))) { + multiVolumeCheckbox->setChecked(true); + // Convert from kilobytes. + volumeSizeSpinbox->setValue(m_opts.value(QStringLiteral("VolumeSize")).toDouble() / 1024); + } } CompressionOptions CompressionOptionsWidget::commpressionOptions() const { CompressionOptions opts; opts[QStringLiteral("CompressionLevel")] = compLevelSlider->value(); + if (multiVolumeCheckbox->isChecked()) { + // Convert to kilobytes. + opts[QStringLiteral("VolumeSize")] = QString::number(volumeSize()); + } return opts; } @@ -62,6 +74,16 @@ return compLevelSlider->value(); } +ulong CompressionOptionsWidget::volumeSize() const +{ + if (collapsibleMultiVolume->isEnabled() && multiVolumeCheckbox->isChecked()) { + // Convert to kilobytes. + return volumeSizeSpinbox->value() * 1024; + } else { + return 0; + } +} + void CompressionOptionsWidget::setEncryptionVisible(bool visible) { collapsibleEncryption->setVisible(visible); @@ -122,6 +144,15 @@ compLevelSlider->setValue(archiveFormat.defaultCompressionLevel()); } } + + if (archiveFormat.supportsMultiVolume()) { + collapsibleMultiVolume->setEnabled(true); + collapsibleMultiVolume->setToolTip(QString()); + } else { + collapsibleMultiVolume->setEnabled(false); + collapsibleMultiVolume->setToolTip(i18n("The %1 format does not support multi-volume archives.", + m_mimetype.comment())); + } } void CompressionOptionsWidget::setMimeType(const QMimeType &mimeType) @@ -155,4 +186,15 @@ return pwdWidget->passwordStatus(); } +void CompressionOptionsWidget::slotMultiVolumeChecked(int state) +{ + if (state == Qt::Checked) { + lblVolumeSize->setEnabled(true); + volumeSizeSpinbox->setEnabled(true); + } else { + lblVolumeSize->setEnabled(false); + volumeSizeSpinbox->setEnabled(false); + } +} + } diff --git a/kerfuffle/compressionoptionswidget.ui b/kerfuffle/compressionoptionswidget.ui --- a/kerfuffle/compressionoptionswidget.ui +++ b/kerfuffle/compressionoptionswidget.ui @@ -6,8 +6,8 @@ 0 0 - 384 - 62 + 401 + 90 @@ -106,7 +106,7 @@ - + false @@ -131,6 +131,73 @@ + + + + Multi-volume Archive + + + false + + + + + + Create multi-volume archive + + + + + + + 0 + + + 30 + + + + + false + + + Volume size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + megabytes + + + 1 + + + 0.100000000000000 + + + 1000.000000000000000 + + + 0.500000000000000 + + + 1.000000000000000 + + + + + + + + @@ -143,7 +210,7 @@ KNewPasswordWidget QWidget -
KNewPasswordWidget
+
knewpasswordwidget.h
1
diff --git a/kerfuffle/createdialog.h b/kerfuffle/createdialog.h --- a/kerfuffle/createdialog.h +++ b/kerfuffle/createdialog.h @@ -59,6 +59,7 @@ QMimeType currentMimeType() const; bool setMimeType(const QString &mimeTypeName); int compressionLevel() const; + ulong volumeSize() const; /** * @return Whether the user can encrypt the new archive. diff --git a/kerfuffle/createdialog.cpp b/kerfuffle/createdialog.cpp --- a/kerfuffle/createdialog.cpp +++ b/kerfuffle/createdialog.cpp @@ -151,6 +151,11 @@ return m_ui->optionsWidget->compressionLevel(); } +ulong CreateDialog::volumeSize() const +{ + return m_ui->optionsWidget->volumeSize(); +} + QString CreateDialog::password() const { return m_ui->optionsWidget->password(); diff --git a/part/part.cpp b/part/part.cpp --- a/part/part.cpp +++ b/part/part.cpp @@ -409,7 +409,8 @@ void Part::updateActions() { - bool isWritable = m_model->archive() && !m_model->archive()->isReadOnly(); + bool isWritable = m_model->archive() && !m_model->archive()->isReadOnly() && + !(m_model->rowCount() > 0 && m_model->archive()->isMultiVolume()); bool isDirectory = m_model->entryForIndex(m_view->selectionModel()->currentIndex())[IsDirectory].toBool(); int selectedEntriesCount = m_view->selectionModel()->selectedRows().count(); @@ -663,6 +664,10 @@ Q_ASSERT(archive->isValid()); + if (arguments().metaData().contains(QStringLiteral("volumeSize"))) { + archive.data()->setMultiVolume(true); + } + // Plugin loaded successfully. KJob *job = m_model->setArchive(archive.take()); if (job) { @@ -1243,6 +1248,9 @@ if (arguments().metaData().contains(QStringLiteral("compressionLevel"))) { opts[QStringLiteral("CompressionLevel")] = arguments().metaData()[QStringLiteral("compressionLevel")]; } + if (arguments().metaData().contains(QStringLiteral("volumeSize"))) { + opts[QStringLiteral("VolumeSize")] = arguments().metaData()[QStringLiteral("volumeSize")]; + } m_model->archive()->setCompressionOptions(opts); } else { opts = m_model->archive()->compressionOptions(); @@ -1282,6 +1290,17 @@ } else { // Hide the "archive will be created as soon as you add a file" message. m_messageWidget->hide(); + + // For multi-volume archive, we need to re-open the archive after adding files + // because the name changes from e.g name.rar to name.part1.rar. + if (m_model->archive()->isMultiVolume()) { + qCDebug(ARK) << "Multi-volume archive detected, re-opening..."; + KParts::OpenUrlArguments args = arguments(); + args.metaData()[QStringLiteral("createNewArchive")] = QStringLiteral("false"); + setArguments(args); + + openUrl(QUrl::fromLocalFile(m_model->archive()->multiVolumeName())); + } } } diff --git a/plugins/cli7zplugin/cliplugin.cpp b/plugins/cli7zplugin/cliplugin.cpp --- a/plugins/cli7zplugin/cliplugin.cpp +++ b/plugins/cli7zplugin/cliplugin.cpp @@ -79,6 +79,7 @@ << QStringLiteral("$Archive") << QStringLiteral("$PasswordSwitch") << QStringLiteral("$CompressionLevelSwitch") + << QStringLiteral("$MultiVolumeSwitch") << QStringLiteral("$Files"); p[DeleteArgs] = QStringList() << QStringLiteral("d") << QStringLiteral("$PasswordSwitch") @@ -104,6 +105,8 @@ p[CorruptArchivePatterns] = QStringList() << QStringLiteral("Unexpected end of archive") << QStringLiteral("Headers Error"); p[DiskFullPatterns] = QStringList() << QStringLiteral("No space left on device"); + p[MultiVolumeSwitch] = QStringLiteral("-v$VolumeSizek"); + p[MultiVolumeSuffix] = QStringList() << QStringLiteral("$Suffix.001"); } return p; @@ -161,7 +164,7 @@ } else if (type == QLatin1String("Rar")) { m_archiveType = ArchiveTypeRar; } else if (type == QLatin1String("Split")) { - m_isMultiVolume = true; + setMultiVolume(true); } else { // Should not happen qCWarning(ARK) << "Unsupported archive type"; diff --git a/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake b/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake --- a/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake +++ b/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake @@ -47,13 +47,15 @@ "CompressionLevelMax": 9, "CompressionLevelMin": 0, "SupportsTesting": true, - "HeaderEncryption": true + "HeaderEncryption": true, + "SupportsMultiVolume": true }, "application/zip": { "CompressionLevelDefault": 5, "CompressionLevelMax": 9, "CompressionLevelMin": 0, "SupportsTesting": true, - "Encryption": true + "Encryption": true, + "SupportsMultiVolume": true } } diff --git a/plugins/clirarplugin/cliplugin.cpp b/plugins/clirarplugin/cliplugin.cpp --- a/plugins/clirarplugin/cliplugin.cpp +++ b/plugins/clirarplugin/cliplugin.cpp @@ -95,6 +95,7 @@ p[PasswordSwitch] = QStringList() << QStringLiteral( "-p$Password" ); p[PasswordHeaderSwitch] = QStringList() << QStringLiteral("-hp$Password"); p[CompressionLevelSwitch] = QStringLiteral("-m$CompressionLevel"); + p[MultiVolumeSwitch] = QStringLiteral("-v$VolumeSizek"); p[DeleteArgs] = QStringList() << QStringLiteral( "d" ) << QStringLiteral( "$PasswordSwitch" ) << QStringLiteral( "$Archive" ) @@ -112,6 +113,7 @@ << QStringLiteral( "$Archive" ) << QStringLiteral("$PasswordSwitch") << QStringLiteral("$CompressionLevelSwitch") + << QStringLiteral("$MultiVolumeSwitch") << QStringLiteral( "$Files" ); p[PasswordPromptPattern] = QLatin1String("Enter password \\(will not be echoed\\) for"); p[WrongPasswordPatterns] = QStringList() << QStringLiteral("password incorrect") << QStringLiteral("wrong password"); @@ -128,6 +130,10 @@ << QStringLiteral("$Archive") << QStringLiteral("$PasswordSwitch"); p[TestPassedPattern] = QStringLiteral("^All OK$"); + // rar will sometimes create multi-volume archives where first volume is + // called name.part1.rar and other times name.part01.rar. + p[MultiVolumeSuffix] = QStringList() << QStringLiteral("part01.$Suffix") + << QStringLiteral("part1.$Suffix"); } return p; @@ -208,8 +214,8 @@ ignoreLines(1, ParseStateEntryDetails); if (line.contains(QLatin1String("volume"))) { m_numberOfVolumes++; - if (!m_isMultiVolume) { - m_isMultiVolume = true; + if (!isMultiVolume()) { + setMultiVolume(true); qCDebug(ARK) << "Multi-volume archive detected"; } } @@ -313,8 +319,8 @@ if (line.startsWith(QLatin1String("Volume "))) { m_numberOfVolumes++; - if (!m_isMultiVolume) { - m_isMultiVolume = true; + if (!isMultiVolume()) { + setMultiVolume(true); qCDebug(ARK) << "Multi-volume archive detected"; } } diff --git a/plugins/clirarplugin/kerfuffle_clirar.json.cmake b/plugins/clirarplugin/kerfuffle_clirar.json.cmake --- a/plugins/clirarplugin/kerfuffle_clirar.json.cmake +++ b/plugins/clirarplugin/kerfuffle_clirar.json.cmake @@ -51,6 +51,7 @@ "CompressionLevelMin": 0, "SupportsWriteComment": true, "SupportsTesting": true, - "HeaderEncryption": true + "HeaderEncryption": true, + "SupportsMultiVolume": true } }