ark: rework extraction dialog

less space used by the options, automatic sub-folder detection even for
single folder archive and handling of dot (".") as the returned sub-folder
name by the archive list job (libarchive quirck).

tested batch and non-batch extraction, with and without automatic
sub-folder detection but with tar.xz and .deb files only

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-18 03:08:36 +03:00
parent ddcd646ea0
commit c0c0f194bc
6 changed files with 55 additions and 259 deletions

View file

@ -68,7 +68,7 @@ void BatchExtract::addExtraction(Kerfuffle::Archive* archive)
{
QString destination = destinationFolder();
if ((autoSubfolder()) && (!archive->isSingleFolderArchive())) {
if (autoSubfolder()) {
const QDir d(destination);
QString subfolderName = archive->subfolderName();
@ -78,7 +78,10 @@ void BatchExtract::addExtraction(Kerfuffle::Archive* archive)
d.mkdir(subfolderName);
destination += QLatin1Char( '/' ) + subfolderName;
if (!destination.endsWith(QDir::separator())) {
destination += QDir::separator();
}
destination += subfolderName;
}
Kerfuffle::ExtractionOptions options;
@ -254,8 +257,7 @@ void BatchExtract::setPreservePaths(bool value)
bool BatchExtract::showExtractDialog()
{
QWeakPointer<Kerfuffle::ExtractionDialog> dialog =
new Kerfuffle::ExtractionDialog;
QWeakPointer<Kerfuffle::ExtractionDialog> dialog = new Kerfuffle::ExtractionDialog();
if (m_inputs.size() > 1) {
dialog.data()->batchModeOption();
@ -265,13 +267,6 @@ bool BatchExtract::showExtractDialog()
dialog.data()->setUrl(destinationFolder());
dialog.data()->setPreservePaths(preservePaths());
if (m_inputs.size() == 1) {
if (m_inputs.at(0)->isSingleFolderArchive()) {
dialog.data()->setSingleFolderArchive(true);
}
dialog.data()->setSubfolder(m_inputs.at(0)->subfolderName());
}
if (!dialog.data()->exec()) {
delete dialog.data();
return false;

View file

@ -198,17 +198,18 @@ void Archive::onListFinished(KJob* job)
m_isSingleFolderArchive = ljob->isSingleFolderArchive();
m_isPasswordProtected = ljob->isPasswordProtected();
m_subfolderName = ljob->subfolderName();
if (m_subfolderName.isEmpty()) {
if (m_subfolderName.isEmpty() || m_subfolderName == QLatin1String(".")) {
QFileInfo fi(fileName());
QString base = fi.completeBaseName();
//special case for tar.gz/bzip2 files
// special case for tar.gz/bzip2 files
if (base.right(4).toUpper() == QLatin1String(".TAR")) {
base.chop(4);
}
m_subfolderName = base;
}
kDebug() << "Guessed sub-folder" << m_subfolderName;
m_hasBeenListed = true;
}
@ -227,6 +228,7 @@ void Archive::listIfNotListed()
&loop, SLOT(quit()));
job->start();
loop.exec(); // krazy:exclude=crashy
job->deleteLater();
}
}

View file

@ -64,14 +64,6 @@ ExtractionDialog::ExtractionDialog(QWidget *parent)
setCaption(i18nc("@title:window", "Extract"));
m_ui->filesToExtractGroupBox->hide();
m_ui->allFilesButton->setChecked(true);
m_ui->extractAllLabel->show();
setSingleFolderArchive(false);
m_ui->autoSubfolders->hide();
loadSettings();
connect(this, SIGNAL(finished(int)), SLOT(writeSettings()));
@ -84,93 +76,12 @@ void ExtractionDialog::loadSettings()
setPreservePaths(ArkSettings::preservePaths());
}
void ExtractionDialog::setSingleFolderArchive(bool value)
{
m_ui->singleFolderGroup->setChecked(!value);
}
void ExtractionDialog::batchModeOption()
{
m_ui->autoSubfolders->show();
m_ui->autoSubfolders->setEnabled(true);
m_ui->singleFolderGroup->hide();
m_ui->extractAllLabel->setText(i18n("Extract multiple archives"));
}
void ExtractionDialog::accept()
{
if (extractToSubfolder()) {
if (subfolder().contains(QLatin1String( "/" ))) {
KMessageBox::error(NULL, i18n("The subfolder name may not contain the character '/'."));
return;
}
const QString pathWithSubfolder = selectedUrl().pathOrUrl(KUrl::AddTrailingSlash) + subfolder();
while (1) {
if (KIO::NetAccess::exists(pathWithSubfolder, KIO::NetAccess::SourceSide, 0)) {
if (QFileInfo(pathWithSubfolder).isDir()) {
int overwrite = KMessageBox::questionYesNoCancel(0, i18nc("@info", "The folder <tt>%1</tt> already exists. Are you sure you want to extract here?", pathWithSubfolder), i18n("Folder exists"), KGuiItem(i18n("Extract here")), KGuiItem(i18n("Retry")), KGuiItem(i18n("Cancel")));
if (overwrite == KMessageBox::No) {
// The user clicked Retry.
continue;
} else if (overwrite == KMessageBox::Cancel) {
return;
}
} else {
KMessageBox::detailedError(0,
i18nc("@info", "The folder <tt>%1</tt> could not be created.", subfolder()),
i18nc("@info", "<tt>%1</tt> already exists, but is not a folder.", subfolder()));
return;
}
} else if (!KIO::NetAccess::mkdir(pathWithSubfolder, 0)) {
KMessageBox::detailedError(0,
i18nc("@info", "The folder <tt>%1</tt> could not be created.", subfolder()),
i18n("Please check your permissions to create it."));
return;
}
break;
}
}
KFileDialog::accept();
}
void ExtractionDialog::setSubfolder(const QString& subfolder)
{
m_ui->subfolder->setText(subfolder);
}
QString ExtractionDialog::subfolder() const
{
return m_ui->subfolder->text();
}
ExtractionDialog::~ExtractionDialog()
{
delete m_ui;
m_ui = 0;
}
void ExtractionDialog::setShowSelectedFiles(bool value)
{
if (value) {
m_ui->filesToExtractGroupBox->show();
m_ui->selectedFilesButton->setChecked(true);
m_ui->extractAllLabel->hide();
} else {
m_ui->filesToExtractGroupBox->hide();
m_ui->selectedFilesButton->setChecked(false);
m_ui->extractAllLabel->show();
}
}
bool ExtractionDialog::extractAllFiles() const
{
return m_ui->allFilesButton->isChecked();
}
void ExtractionDialog::setAutoSubfolder(bool value)
{
m_ui->autoSubfolders->setChecked(value);
@ -181,11 +92,6 @@ bool ExtractionDialog::autoSubfolders() const
return m_ui->autoSubfolders->isChecked();
}
bool ExtractionDialog::extractToSubfolder() const
{
return m_ui->singleFolderGroup->isChecked();
}
void ExtractionDialog::setOpenDestinationFolderAfterExtraction(bool value)
{
m_ui->openFolderCheckBox->setChecked(value);
@ -218,11 +124,17 @@ bool ExtractionDialog::closeAfterExtraction() const
QString ExtractionDialog::destinationDirectory() const
{
const KUrl selected = selectedUrl();
if (extractToSubfolder()) {
return selected.pathOrUrl(KUrl::AddTrailingSlash) + subfolder() + QLatin1Char( '/' );
}
return selected.pathOrUrl(KUrl::AddTrailingSlash);
return selectedUrl().pathOrUrl(KUrl::AddTrailingSlash);
}
void ExtractionDialog::selectionModeOption()
{
setCaption(i18n("Extract selected"));
}
void ExtractionDialog::batchModeOption()
{
setCaption(i18n("Extract multiple archives"));
}
void ExtractionDialog::writeSettings()

View file

@ -44,26 +44,19 @@ public:
ExtractionDialog(QWidget *parent = 0);
virtual ~ExtractionDialog();
void setShowSelectedFiles(bool);
void setSingleFolderArchive(bool);
void setPreservePaths(bool);
void batchModeOption();
void setOpenDestinationFolderAfterExtraction(bool);
void setCloseAfterExtraction(bool);
void setAutoSubfolder(bool value);
bool extractAllFiles() const;
bool openDestinationAfterExtraction() const;
bool closeAfterExtraction() const;
bool extractToSubfolder() const;
bool autoSubfolders() const;
bool preservePaths() const;
QString destinationDirectory() const;
QString subfolder() const;
virtual void accept();
public Q_SLOTS:
void setSubfolder(const QString& subfolder);
void selectionModeOption();
void batchModeOption();
private Q_SLOTS:
void writeSettings();

View file

@ -20,58 +20,6 @@
<string>Extraction Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QLabel" name="extractAllLabel" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Maximum" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font" >
<font>
<pointsize>15</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text" >
<string>Extract All Files</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="singleFolderGroup" >
<property name="title" >
<string>&amp;Extraction into subfolder:</string>
</property>
<property name="checkable" >
<bool>true</bool>
</property>
<property name="checked" >
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="KLineEdit" name="subfolder" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="showClearButton" stdset="0" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="sizePolicy" >
@ -83,42 +31,29 @@
<property name="title" >
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="6" column="0" >
<spacer name="verticalSpacer" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" >
<layout class="QVBoxLayout" name="verticalLayout" >
<item row="0" column="0" >
<widget class="QCheckBox" name="openFolderCheckBox" >
<property name="text" >
<string>Open &amp;destination folder after extraction</string>
</property>
</widget>
</item>
<item row="3" column="0" >
<item row="1" column="0" >
<widget class="QCheckBox" name="closeAfterExtraction" >
<property name="text" >
<string>Close &amp;Ark after extraction</string>
</property>
</widget>
</item>
<item row="4" column="0" >
<item row="2" column="0" >
<widget class="QCheckBox" name="preservePaths" >
<property name="text" >
<string>&amp;Preserve paths when extracting</string>
</property>
</widget>
</item>
<item row="5" column="0" >
<item row="3" column="0" >
<widget class="QCheckBox" name="autoSubfolders" >
<property name="text" >
<string>&amp;Automatically create subfolders</string>
@ -128,56 +63,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="filesToExtractGroupBox" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title" >
<string comment="@title:group">Extract</string>
</property>
<property name="flat" >
<bool>false</bool>
</property>
<property name="checkable" >
<bool>false</bool>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QRadioButton" name="selectedFilesButton" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>&amp;Selected files only</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="allFilesButton" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>All &amp;files</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>

View file

@ -43,6 +43,7 @@
#include <KGuiItem>
#include <KIO/Job>
#include <KIO/NetAccess>
#include <KIO/RenameDialog>
#include <KIcon>
#include <KInputDialog>
#include <KMenu>
@ -660,31 +661,20 @@ void Part::slotExtractFiles()
return;
}
QWeakPointer<Kerfuffle::ExtractionDialog> dialog = new Kerfuffle::ExtractionDialog;
QVariantList files = selectedFilesWithChildren();
kDebug() << "Selected" << files;
if (m_view->selectionModel()->selectedRows().count() > 0) {
dialog.data()->setShowSelectedFiles(true);
}
dialog.data()->setSingleFolderArchive(isSingleFolderArchive());
dialog.data()->setSubfolder(detectSubfolder());
QWeakPointer<Kerfuffle::ExtractionDialog> dialog = new Kerfuffle::ExtractionDialog();
dialog.data()->setUrl(QFileInfo(m_model->archive()->fileName()).path());
if (!files.isEmpty()) {
dialog.data()->selectionModeOption();
}
if (dialog.data()->exec()) {
//this is done to update the quick extract menu
updateActions();
QVariantList files;
//if the user has chosen to extract only selected entries, fetch these
//from the listview
if (!dialog.data()->extractAllFiles()) {
files = selectedFilesWithChildren();
}
kDebug() << "Selected " << files;
Kerfuffle::ExtractionOptions options;
if (dialog.data()->preservePaths()) {
@ -693,7 +683,26 @@ void Part::slotExtractFiles()
options[QLatin1String("FollowExtractionDialogSettings")] = true;
const QString destinationDirectory = dialog.data()->destinationDirectory();
QString destinationDirectory = dialog.data()->destinationDirectory();
if (dialog.data()->autoSubfolders()) {
QString subFolder = detectSubfolder();
if (!subFolder.isEmpty()) {
// do what batch extraction does, create the folder or automatically pick other if it
// exists
const QDir destDir(destinationDirectory);
if (destDir.exists(subFolder)) {
subFolder = KIO::RenameDialog::suggestName(destinationDirectory, subFolder);
}
destDir.mkdir(subFolder);
if (!destinationDirectory.endsWith(QDir::separator())) {
destinationDirectory += QDir::separator();
}
destinationDirectory += subFolder;
}
}
kDebug() << "Destination" << destinationDirectory;
ExtractJob *job = m_model->extractFiles(files, destinationDirectory, options);
registerJob(job);