]> cloud.milkyroute.net Git - dolphin.git/blob - src/settings/services/servicessettingspage.cpp
ba6c48f80bc8366c4232ca56a480dd8306a2b3eb
[dolphin.git] / src / settings / services / servicessettingspage.cpp
1 /***************************************************************************
2 * Copyright (C) 2009-2010 by Peter Penz <peter.penz19@gmail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "servicessettingspage.h"
21
22 #include "dolphin_generalsettings.h"
23 #include "dolphin_versioncontrolsettings.h"
24 #include "settings/serviceitemdelegate.h"
25 #include "settings/servicemodel.h"
26
27 #include <KDesktopFile>
28 #include <KLocalizedString>
29 #include <KMessageBox>
30 #include <KNS3/Button>
31 #include <KPluginMetaData>
32 #include <KService>
33 #include <KServiceTypeTrader>
34 #include <kdesktopfileactions.h>
35
36 #include <QGridLayout>
37 #include <QLabel>
38 #include <QListWidget>
39 #include <QShowEvent>
40 #include <QSortFilterProxyModel>
41 #include <QLineEdit>
42
43 namespace
44 {
45 const bool ShowDeleteDefault = false;
46 const char VersionControlServicePrefix[] = "_version_control_";
47 const char DeleteService[] = "_delete";
48 const char CopyToMoveToService[] ="_copy_to_move_to";
49 }
50
51 ServicesSettingsPage::ServicesSettingsPage(QWidget* parent) :
52 SettingsPageBase(parent),
53 m_initialized(false),
54 m_serviceModel(nullptr),
55 m_sortModel(nullptr),
56 m_listView(nullptr),
57 m_enabledVcsPlugins()
58 {
59 QVBoxLayout* topLayout = new QVBoxLayout(this);
60
61 QLabel* label = new QLabel(i18nc("@label:textbox",
62 "Select which services should "
63 "be shown in the context menu:"), this);
64 label->setWordWrap(true);
65 m_searchLineEdit = new QLineEdit(this);
66 m_searchLineEdit->setPlaceholderText(i18nc("@label:textbox", "Search..."));
67 connect(m_searchLineEdit, &QLineEdit::textChanged, this, [=](const QString &filter){
68 m_sortModel->setFilterFixedString(filter);
69 });
70
71 m_listView = new QListView(this);
72 ServiceItemDelegate* delegate = new ServiceItemDelegate(m_listView, m_listView);
73 m_serviceModel = new ServiceModel(this);
74 m_sortModel = new QSortFilterProxyModel(this);
75 m_sortModel->setSourceModel(m_serviceModel);
76 m_sortModel->setSortRole(Qt::DisplayRole);
77 m_sortModel->setSortLocaleAware(true);
78 m_sortModel->setFilterRole(Qt::DisplayRole);
79 m_sortModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
80 m_listView->setModel(m_sortModel);
81 m_listView->setItemDelegate(delegate);
82 m_listView->setVerticalScrollMode(QListView::ScrollPerPixel);
83 connect(m_listView, &QListView::clicked, this, &ServicesSettingsPage::changed);
84
85 KNS3::Button* downloadButton = new KNS3::Button(i18nc("@action:button", "Download New Services..."),
86 QStringLiteral("servicemenu.knsrc"),
87 this);
88 connect(downloadButton, &KNS3::Button::dialogFinished, this, &ServicesSettingsPage::loadServices);
89
90 topLayout->addWidget(label);
91 topLayout->addWidget(m_searchLineEdit);
92 topLayout->addWidget(m_listView);
93 topLayout->addWidget(downloadButton);
94
95 m_enabledVcsPlugins = VersionControlSettings::enabledPlugins();
96 std::sort(m_enabledVcsPlugins.begin(), m_enabledVcsPlugins.end());
97 }
98
99 ServicesSettingsPage::~ServicesSettingsPage()
100 {
101 }
102
103 void ServicesSettingsPage::applySettings()
104 {
105 if (!m_initialized) {
106 return;
107 }
108
109 KConfig config(QStringLiteral("kservicemenurc"), KConfig::NoGlobals);
110 KConfigGroup showGroup = config.group("Show");
111
112 QStringList enabledPlugins;
113
114 const QAbstractItemModel* model = m_listView->model();
115 for (int i = 0; i < model->rowCount(); ++i) {
116 const QModelIndex index = model->index(i, 0);
117 const QString service = model->data(index, ServiceModel::DesktopEntryNameRole).toString();
118 const bool checked = model->data(index, Qt::CheckStateRole).toBool();
119
120 if (service.startsWith(VersionControlServicePrefix)) {
121 if (checked) {
122 enabledPlugins.append(model->data(index, Qt::DisplayRole).toString());
123 }
124 } else if (service == QLatin1String(DeleteService)) {
125 KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::NoGlobals);
126 KConfigGroup configGroup(globalConfig, "KDE");
127 configGroup.writeEntry("ShowDeleteCommand", checked);
128 configGroup.sync();
129 } else if (service == QLatin1String(CopyToMoveToService)) {
130 GeneralSettings::setShowCopyMoveMenu(checked);
131 GeneralSettings::self()->save();
132 } else {
133 showGroup.writeEntry(service, checked);
134 }
135 }
136
137 showGroup.sync();
138
139 if (m_enabledVcsPlugins != enabledPlugins) {
140 VersionControlSettings::setEnabledPlugins(enabledPlugins);
141 VersionControlSettings::self()->save();
142
143 KMessageBox::information(window(),
144 i18nc("@info", "Dolphin must be restarted to apply the "
145 "updated version control systems settings."),
146 QString(), // default title
147 QStringLiteral("ShowVcsRestartInformation"));
148 }
149 }
150
151 void ServicesSettingsPage::restoreDefaults()
152 {
153 QAbstractItemModel* model = m_listView->model();
154 for (int i = 0; i < model->rowCount(); ++i) {
155 const QModelIndex index = model->index(i, 0);
156 const QString service = model->data(index, ServiceModel::DesktopEntryNameRole).toString();
157
158 const bool checked = !service.startsWith(VersionControlServicePrefix)
159 && service != QLatin1String(DeleteService)
160 && service != QLatin1String(CopyToMoveToService);
161 model->setData(index, checked, Qt::CheckStateRole);
162 }
163 }
164
165 void ServicesSettingsPage::showEvent(QShowEvent* event)
166 {
167 if (!event->spontaneous() && !m_initialized) {
168 loadServices();
169
170 loadVersionControlSystems();
171
172 // Add "Show 'Delete' command" as service
173 KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::IncludeGlobals);
174 KConfigGroup configGroup(globalConfig, "KDE");
175 addRow(QStringLiteral("edit-delete"),
176 i18nc("@option:check", "Delete"),
177 DeleteService,
178 configGroup.readEntry("ShowDeleteCommand", ShowDeleteDefault));
179
180 // Add "Show 'Copy To' and 'Move To' commands" as service
181 addRow(QStringLiteral("edit-copy"),
182 i18nc("@option:check", "'Copy To' and 'Move To' commands"),
183 CopyToMoveToService,
184 GeneralSettings::showCopyMoveMenu());
185
186 m_sortModel->sort(Qt::DisplayRole);
187
188 m_initialized = true;
189 }
190 SettingsPageBase::showEvent(event);
191 }
192
193 void ServicesSettingsPage::loadServices()
194 {
195 const KConfig config(QStringLiteral("kservicemenurc"), KConfig::NoGlobals);
196 const KConfigGroup showGroup = config.group("Show");
197
198 // Load generic services
199 const KService::List entries = KServiceTypeTrader::self()->query(QStringLiteral("KonqPopupMenu/Plugin"));
200 foreach (const KService::Ptr& service, entries) {
201 const QString file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kservices5/" % service->entryPath());
202 const QList<KServiceAction> serviceActions =
203 KDesktopFileActions::userDefinedServices(file, true);
204
205 KDesktopFile desktopFile(file);
206 const QString subMenuName = desktopFile.desktopGroup().readEntry("X-KDE-Submenu");
207
208 foreach (const KServiceAction& action, serviceActions) {
209 const QString serviceName = action.name();
210 const bool addService = !action.noDisplay()
211 && !action.isSeparator()
212 && !isInServicesList(serviceName);
213
214 if (addService) {
215 const QString itemName = subMenuName.isEmpty()
216 ? action.text()
217 : i18nc("@item:inmenu", "%1: %2", subMenuName, action.text());
218 const bool checked = showGroup.readEntry(serviceName, true);
219 addRow(action.icon(), itemName, serviceName, checked);
220 }
221 }
222 }
223
224 // Load service plugins that implement the KFileItemActionPlugin interface
225 const KService::List pluginServices = KServiceTypeTrader::self()->query(QStringLiteral("KFileItemAction/Plugin"));
226 foreach (const KService::Ptr& service, pluginServices) {
227 const QString desktopEntryName = service->desktopEntryName();
228 if (!isInServicesList(desktopEntryName)) {
229 const bool checked = showGroup.readEntry(desktopEntryName, true);
230 addRow(service->icon(), service->name(), desktopEntryName, checked);
231 }
232 }
233
234 // Load JSON-based plugins that implement the KFileItemActionPlugin interface
235 const auto jsonPlugins = KPluginLoader::findPlugins(QStringLiteral("kf5/kfileitemaction"), [](const KPluginMetaData& metaData) {
236 return metaData.serviceTypes().contains(QLatin1String("KFileItemAction/Plugin"));
237 });
238
239 foreach (const auto& jsonMetadata, jsonPlugins) {
240 const QString desktopEntryName = jsonMetadata.pluginId();
241 if (!isInServicesList(desktopEntryName)) {
242 const bool checked = showGroup.readEntry(desktopEntryName, true);
243 addRow(jsonMetadata.iconName(), jsonMetadata.name(), desktopEntryName, checked);
244 }
245 }
246
247 m_sortModel->sort(Qt::DisplayRole);
248 m_searchLineEdit->setFocus(Qt::OtherFocusReason);
249 }
250
251 void ServicesSettingsPage::loadVersionControlSystems()
252 {
253 const QStringList enabledPlugins = VersionControlSettings::enabledPlugins();
254
255 // Create a checkbox for each available version control plugin
256 const KService::List pluginServices = KServiceTypeTrader::self()->query(QStringLiteral("FileViewVersionControlPlugin"));
257 for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) {
258 const QString pluginName = (*it)->name();
259 addRow(QStringLiteral("code-class"),
260 pluginName,
261 VersionControlServicePrefix + pluginName,
262 enabledPlugins.contains(pluginName));
263 }
264
265 m_sortModel->sort(Qt::DisplayRole);
266 }
267
268 bool ServicesSettingsPage::isInServicesList(const QString& service) const
269 {
270 for (int i = 0; i < m_serviceModel->rowCount(); ++i) {
271 const QModelIndex index = m_serviceModel->index(i, 0);
272 if (m_serviceModel->data(index, ServiceModel::DesktopEntryNameRole).toString() == service) {
273 return true;
274 }
275 }
276 return false;
277 }
278
279 void ServicesSettingsPage::addRow(const QString& icon,
280 const QString& text,
281 const QString& value,
282 bool checked)
283 {
284 m_serviceModel->insertRow(0);
285
286 const QModelIndex index = m_serviceModel->index(0, 0);
287 m_serviceModel->setData(index, icon, Qt::DecorationRole);
288 m_serviceModel->setData(index, text, Qt::DisplayRole);
289 m_serviceModel->setData(index, value, ServiceModel::DesktopEntryNameRole);
290 m_serviceModel->setData(index, checked, Qt::CheckStateRole);
291 }
292