1 /*
2 SPDX-FileCopyrightText: 2016 Elvis Angelaccio <elvis.angelaccio@kde.org>
3 SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "compressfileitemaction.h"
9
10 #include <QMenu>
11 #include <QMimeDatabase>
12
13 #include <KFileItem>
14 #include <KIO/ApplicationLauncherJob>
15 #include <KLocalizedString>
16 #include <KPluginFactory>
17
18 #include <algorithm>
19
20 #include "pluginmanager.h"
21 #include "addtoarchive.h"
22
23 K_PLUGIN_CLASS_WITH_JSON(CompressFileItemAction, "compressfileitemaction.json")
24
25 using namespace Kerfuffle;
26
CompressFileItemAction(QObject * parent,const QVariantList &)27 CompressFileItemAction::CompressFileItemAction(QObject* parent, const QVariantList&)
28 : KAbstractFileItemActionPlugin(parent)
29 , m_pluginManager(new PluginManager(this))
30 {}
31
actions(const KFileItemListProperties & fileItemInfos,QWidget * parentWidget)32 QList<QAction*> CompressFileItemAction::actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget)
33 {
34 // #268163: don't offer compression on already compressed archives, unless the user selected 2 or more of them.
35 if (fileItemInfos.items().count() == 1 && m_pluginManager->supportedMimeTypes().contains(fileItemInfos.mimeType())) {
36 return {};
37 }
38
39 // KFileItemListProperties::isLocal() doesn't check target URL (e.g. files on the desktop)
40 const auto urlList = fileItemInfos.urlList();
41 const bool hasLocalUrl = std::any_of(urlList.begin(), urlList.end(), [](const QUrl &url) {
42 return url.isLocalFile();
43 });
44
45 if (!hasLocalUrl) {
46 return {};
47 }
48
49 QList<QAction*> actions;
50 const QIcon icon = QIcon::fromTheme(QStringLiteral("archive-insert"));
51
52 QMenu *compressMenu = new QMenu(parentWidget);
53
54 compressMenu->addAction(createAction(icon,
55 i18nc("@action:inmenu Part of Compress submenu in Dolphin context menu", "Here (as TAR.GZ)"),
56 parentWidget,
57 urlList,
58 QStringLiteral("tar.gz")));
59
60 const QMimeType zipMime = QMimeDatabase().mimeTypeForName(QStringLiteral("application/zip"));
61 // Don't offer zip compression if no zip plugin is available.
62 if (!m_pluginManager->preferredWritePluginsFor(zipMime).isEmpty()) {
63 compressMenu->addAction(createAction(icon,
64 i18nc("@action:inmenu Part of Compress submenu in Dolphin context menu", "Here (as ZIP)"),
65 parentWidget,
66 urlList,
67 QStringLiteral("zip")));
68 }
69
70 compressMenu->addAction(createAction(icon,
71 i18nc("@action:inmenu Part of Compress submenu in Dolphin context menu", "Compress to..."),
72 parentWidget,
73 urlList,
74 QString()));
75
76 QAction *compressMenuAction = new QAction(i18nc("@action:inmenu Compress submenu in Dolphin context menu", "Compress"), parentWidget);
77 compressMenuAction->setMenu(compressMenu);
78 compressMenuAction->setEnabled(fileItemInfos.isLocal() && fileItemInfos.supportsWriting() && !m_pluginManager->availableWritePlugins().isEmpty());
79 compressMenuAction->setIcon(icon);
80
81 actions << compressMenuAction;
82 return actions;
83 }
84
createAction(const QIcon & icon,const QString & name,QWidget * parent,const QList<QUrl> & urls,const QString & fileExtension)85 QAction *CompressFileItemAction::createAction(const QIcon& icon, const QString& name, QWidget *parent, const QList<QUrl>& urls, const QString& fileExtension)
86 {
87 QAction *action = new QAction(icon, name, parent);
88
89 connect(action, &QAction::triggered, this, [fileExtension, urls, name, parent, this]() {
90 auto *addToArchiveJob = new AddToArchive(parent);
91 addToArchiveJob->setChangeToFirstPath(true);
92 for (const QUrl &url : urls) {
93 addToArchiveJob->addInput(url);
94 }
95 if (!fileExtension.isEmpty()) {
96 addToArchiveJob->setAutoFilenameSuffix(fileExtension);
97 } else {
98 if (!addToArchiveJob->showAddDialog()) {
99 delete addToArchiveJob;
100 return;
101 }
102 }
103 addToArchiveJob->start();
104 connect(addToArchiveJob, &KJob::finished, this, [this, addToArchiveJob]() {
105 if (addToArchiveJob->error() != 0) {
106 Q_EMIT error(addToArchiveJob->errorString());
107 }
108 });
109 });
110
111 return action;
112 }
113
114 #include "compressfileitemaction.moc"
115