File indexing completed on 2024-04-28 05:47:34
0001 /* 0002 SPDX-FileCopyrightText: 2016 Elvis Angelaccio <elvis.angelaccio@kde.org> 0003 SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "extractfileitemaction.h" 0009 0010 #include <QFileInfo> 0011 #include <QMenu> 0012 0013 #include <KIO/CopyJob> 0014 #include <KIO/JobUiDelegate> 0015 #include <KIO/OpenFileManagerWindowJob> 0016 #include <KLocalizedString> 0017 #include <KPluginFactory> 0018 0019 #include "batchextract.h" 0020 #include "mimetypes.h" 0021 #include "pluginmanager.h" 0022 #include "settings.h" 0023 0024 K_PLUGIN_CLASS_WITH_JSON(ExtractFileItemAction, "extractfileitemaction.json") 0025 0026 using namespace Kerfuffle; 0027 0028 ExtractFileItemAction::ExtractFileItemAction(QObject *parent, const QVariantList &) 0029 : KAbstractFileItemActionPlugin(parent) 0030 , m_pluginManager(new PluginManager(this)) 0031 { 0032 } 0033 0034 QList<QAction *> ExtractFileItemAction::actions(const KFileItemListProperties &fileItemInfos, QWidget *parentWidget) 0035 { 0036 QList<QAction *> actions; 0037 const QIcon icon = QIcon::fromTheme(QStringLiteral("archive-extract")); 0038 0039 bool readOnlyParentDir = false; 0040 QList<QUrl> supportedUrls; 0041 // Filter URLs by supported mimetypes. 0042 const auto urlList = fileItemInfos.urlList(); 0043 for (const QUrl &url : urlList) { 0044 if (!url.isLocalFile()) { 0045 continue; 0046 } 0047 const QMimeType mimeType = determineMimeType(url.toLocalFile()); 0048 if (m_pluginManager->preferredPluginsFor(mimeType).isEmpty()) { 0049 continue; 0050 } 0051 supportedUrls << url; 0052 // Check whether we can write in the parent directory of the file. 0053 if (!readOnlyParentDir) { 0054 const QString directory = url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile(); 0055 if (!QFileInfo(directory).isWritable()) { 0056 readOnlyParentDir = true; 0057 } 0058 } 0059 } 0060 0061 if (supportedUrls.isEmpty()) { 0062 return {}; 0063 } 0064 0065 QAction *extractToAction = createAction(icon, 0066 i18nc("@action:inmenu Part of Extract submenu in Dolphin context menu", "Extract to…"), 0067 parentWidget, 0068 supportedUrls, 0069 AdditionalJobOptions::ShowDialog); 0070 0071 // #189177: disable "extract here" actions in read-only folders. 0072 if (readOnlyParentDir) { 0073 actions << extractToAction; 0074 } else { 0075 QMenu *extractMenu = new QMenu(parentWidget); 0076 0077 extractMenu->addAction(createAction(icon, 0078 i18nc("@action:inmenu Part of Extract submenu in Dolphin context menu", "Extract here"), 0079 parentWidget, 0080 supportedUrls, 0081 AdditionalJobOptions::None)); 0082 0083 extractMenu->addAction(createAction(QIcon::fromTheme(QStringLiteral("archive-remove")), 0084 i18nc("@action:inmenu Part of Extract submenu in Dolphin context menu", "Extract here and delete archive"), 0085 parentWidget, 0086 supportedUrls, 0087 AdditionalJobOptions::AutoDelete)); 0088 0089 extractMenu->addAction(extractToAction); 0090 0091 QAction *extractMenuAction = new QAction(i18nc("@action:inmenu Extract submenu in Dolphin context menu", "Extract"), parentWidget); 0092 extractMenuAction->setMenu(extractMenu); 0093 extractMenuAction->setIcon(icon); 0094 0095 actions << extractMenuAction; 0096 } 0097 0098 return actions; 0099 } 0100 0101 QAction *ExtractFileItemAction::createAction(const QIcon &icon, const QString &name, QWidget *parent, const QList<QUrl> &urls, AdditionalJobOptions option) 0102 { 0103 QAction *action = new QAction(icon, name, parent); 0104 connect(action, &QAction::triggered, this, [urls, option, this]() { 0105 // Don't pass a parent to the job, otherwise it will be killed if dolphin gets closed. 0106 auto *batchExtractJob = new BatchExtract(nullptr); 0107 batchExtractJob->setDestinationFolder(QFileInfo(urls.first().toLocalFile()).path()); 0108 batchExtractJob->setOpenDestinationAfterExtraction(ArkSettings::openDestinationFolderAfterExtraction()); 0109 if (option == ShowDialog) { 0110 if (!batchExtractJob->showExtractDialog()) { 0111 delete batchExtractJob; 0112 return; 0113 } 0114 } else { 0115 batchExtractJob->setAutoSubfolder(true); 0116 } 0117 for (const QUrl &url : urls) { 0118 batchExtractJob->addInput(url); 0119 } 0120 batchExtractJob->start(); 0121 connect(batchExtractJob, &KJob::finished, this, [this, batchExtractJob, option, urls]() { 0122 if (batchExtractJob->error()) { 0123 Q_EMIT error(batchExtractJob->errorString()); 0124 } else if (option == AutoDelete) { 0125 KIO::Job *job = KIO::trash(urls); 0126 job->uiDelegate()->setAutoErrorHandlingEnabled(true); 0127 } 0128 batchExtractJob->deleteLater(); 0129 }); 0130 }); 0131 return action; 0132 } 0133 0134 #include "extractfileitemaction.moc" 0135 #include "moc_extractfileitemaction.cpp"