]> cloud.milkyroute.net Git - dolphin.git/blob - src/admin/workerintegration.cpp
0b95ec782119a6c6fdca042b001bffc4c12f40cf
[dolphin.git] / src / admin / workerintegration.cpp
1 /*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7
8 #include "workerintegration.h"
9
10 #include "config-dolphin.h"
11 #include "dolphinmainwindow.h"
12 #include "dolphinpackageinstaller.h"
13 #include "dolphinviewcontainer.h"
14
15 #include <KActionCollection>
16 #include <KLocalizedString>
17 #include <KMessageBox>
18 #include <KMessageDialog>
19 #include <KProtocolInfo>
20
21 #include <QAction>
22
23 #include <iostream>
24
25 using namespace Admin;
26
27 /** Free file-local functions */
28 namespace
29 {
30 /** @returns the translated name of the actAsAdminAction. */
31 QString actionName()
32 {
33 return i18nc("@action:inmenu", "Act as Administrator");
34 };
35
36 /** @returns the default keyboard shortcut of the actAsAdminAction. */
37 QKeySequence actionDefaultShortcut()
38 {
39 return Qt::CTRL | Qt::SHIFT | Qt::ALT | Qt::Key_A;
40 };
41
42 /** @returns whether any worker for the protocol "admin" is available. */
43 bool isWorkerInstalled()
44 {
45 return KProtocolInfo::isKnownProtocol(QStringLiteral("admin"));
46 }
47 }
48
49 void Admin::guideUserTowardsInstallingAdminWorker()
50 {
51 if (!isWorkerInstalled()) {
52 std::cout << qPrintable(
53 xi18nc("@info:shell",
54 "<application>Dolphin</application> requires <application>%1</application> to manage system-controlled files, but it is not installed.<nl/>"
55 "Press %2 to install <application>%1</application> or %3 to cancel.",
56 ADMIN_WORKER_PACKAGE_NAME,
57 QKeySequence{Qt::Key_Enter}.toString(QKeySequence::NativeText),
58 QKeySequence{Qt::CTRL | Qt::Key_C}.toString(QKeySequence::NativeText)));
59 std::cin.ignore();
60
61 /// Installing admin worker
62 DolphinPackageInstaller adminWorkerInstaller{ADMIN_WORKER_PACKAGE_NAME, QUrl(QStringLiteral("appstream://org.kde.kio.admin")), isWorkerInstalled};
63 QObject::connect(&adminWorkerInstaller, &KJob::result, [](KJob *job) {
64 if (job->error()) {
65 std::cout << qPrintable(job->errorString()) << std::endl;
66 exit(1);
67 }
68 });
69 adminWorkerInstaller.exec();
70 }
71 }
72
73 void Admin::guideUserTowardsUsingAdminWorker()
74 {
75 KuitSetup *kuitSetup = &Kuit::setupForDomain("dolphin");
76 kuitSetup->setTagPattern(QStringLiteral("numberedlist"), QStringList{}, Kuit::RichText, ki18nc("tag-format-pattern <numberedlist> rich", "<ol>%1</ol>"));
77 kuitSetup->setTagPattern(QStringLiteral("numbereditem"), QStringList{}, Kuit::RichText, ki18nc("tag-format-pattern <numbereditem> rich", "<li>%1</li>"));
78
79 KMessageBox::information(
80 nullptr,
81 xi18nc("@info",
82 "<para>Make use of your administrator rights in Dolphin:<numberedlist>"
83 "<numbereditem>Navigate to the file or folder you want to change.</numbereditem>"
84 "<numbereditem>Activate the \"%1\" action either under <interface>Open Menu|More|View</interface> or <interface>Menu Bar|View</interface>.<nl/>"
85 "Default shortcut: <shortcut>%2</shortcut></numbereditem>"
86 "<numbereditem>After authorization you can manage files as an administrator.</numbereditem></numberedlist></para>",
87 actionName(),
88 actionDefaultShortcut().toString(QKeySequence::NativeText)),
89 i18nc("@title:window", "How to Administrate"),
90 "",
91 KMessageBox::WindowModal);
92 }
93
94 QString Admin::warningMessage()
95 {
96 return xi18nc(
97 "@info",
98 "<para>You are about to use administrator privileges. While acting as an administrator you can change or replace any file or folder on this system. "
99 "This includes items which are critical for this system to function.</para><para>You are able to <emphasis>delete every users' data</emphasis> on this "
100 "computer and to <emphasis>break this installation beyond repair.</emphasis> Adding just one letter in a folder or file name or its contents can "
101 "render a system <emphasis>unbootable.</emphasis></para><para>There is probably not going to be another warning even if you are about to break this "
102 "system.</para><para>You might want to <emphasis>backup files and folders</emphasis> before proceeding.</para>");
103 }
104
105 namespace
106 {
107 /** The only WorkerIntegration object that is ever constructed. It is only ever accessed directly from within this file. */
108 WorkerIntegration *instance = nullptr;
109 }
110
111 WorkerIntegration::WorkerIntegration(DolphinMainWindow *parent, QAction *actAsAdminAction)
112 : QObject{parent}
113 , m_actAsAdminAction{actAsAdminAction}
114 {
115 Q_CHECK_PTR(parent);
116 Q_CHECK_PTR(actAsAdminAction);
117
118 connect(parent, &DolphinMainWindow::urlChanged, this, &WorkerIntegration::updateActAsAdminAction);
119
120 connect(actAsAdminAction, &QAction::triggered, this, &WorkerIntegration::toggleActAsAdmin);
121 }
122
123 void WorkerIntegration::createActAsAdminAction(KActionCollection *actionCollection, DolphinMainWindow *dolphinMainWindow)
124 {
125 Q_ASSERT(!instance);
126 if (isWorkerInstalled()) {
127 QAction *actAsAdminAction = actionCollection->addAction(QStringLiteral("act_as_admin"));
128 actAsAdminAction->setText(actionName());
129 actAsAdminAction->setIcon(QIcon::fromTheme(QStringLiteral("system-switch-user")));
130 actAsAdminAction->setCheckable(true);
131 actionCollection->setDefaultShortcut(actAsAdminAction, actionDefaultShortcut());
132
133 instance = new WorkerIntegration(dolphinMainWindow, actAsAdminAction);
134 }
135 }
136
137 void WorkerIntegration::toggleActAsAdmin()
138 {
139 auto dolphinMainWindow = static_cast<DolphinMainWindow *>(parent());
140 QUrl url = dolphinMainWindow->activeViewContainer()->urlNavigator()->locationUrl();
141
142 if (url.scheme() == QStringLiteral("admin")) {
143 url.setScheme(QStringLiteral("file"));
144 dolphinMainWindow->changeUrl(url);
145 return;
146 } else if (url.scheme() != QStringLiteral("file")) {
147 return;
148 }
149
150 bool risksAccepted = !KMessageBox::shouldBeShownContinue(warningDontShowAgainName);
151
152 if (!risksAccepted) {
153 KMessageDialog warningDialog{KMessageDialog::QuestionTwoActions, warningMessage(), dolphinMainWindow};
154 warningDialog.setCaption(i18nc("@title:window", "Risks of Acting as an Administrator"));
155 warningDialog.setIcon(QIcon::fromTheme(QStringLiteral("security-low")));
156 warningDialog.setButtons(KGuiItem{i18nc("@action:button", "I Understand and Accept These Risks"), QStringLiteral("data-warning")},
157 KStandardGuiItem::cancel());
158 warningDialog.setDontAskAgainText(i18nc("@option:check", "Do not warn me about these risks again"));
159
160 risksAccepted = warningDialog.exec() != 4 /* Cancel */;
161 if (warningDialog.isDontAskAgainChecked()) {
162 KMessageBox::saveDontShowAgainContinue(warningDontShowAgainName);
163 }
164
165 if (!risksAccepted) {
166 updateActAsAdminAction(); // Uncheck the action
167 return;
168 }
169 }
170
171 url.setScheme(QStringLiteral("admin"));
172 dolphinMainWindow->changeUrl(url);
173 }
174
175 void WorkerIntegration::updateActAsAdminAction()
176 {
177 if (instance) {
178 const QString currentUrlScheme = static_cast<DolphinMainWindow *>(instance->parent())->activeViewContainer()->url().scheme();
179 if (currentUrlScheme == QStringLiteral("file")) {
180 instance->m_actAsAdminAction->setEnabled(true);
181 instance->m_actAsAdminAction->setChecked(false);
182 } else if (currentUrlScheme == QStringLiteral("admin")) {
183 instance->m_actAsAdminAction->setEnabled(true);
184 instance->m_actAsAdminAction->setChecked(true);
185 } else {
186 instance->m_actAsAdminAction->setEnabled(false);
187 }
188 }
189 }
190
191 QAction *WorkerIntegration::actAsAdminAction()
192 {
193 return instance->m_actAsAdminAction;
194 }