]> cloud.milkyroute.net Git - dolphin.git/blob - src/admin/workerintegration.cpp
kio-admin: Risk dialog correctly sets url theme
[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 /* We never want to construct more than one instance,
126 however in automatic testing sometimes multiple DolphinMainWindows are created, so this assert is diluted to accommodate for that: */
127 || instance->parent() != dolphinMainWindow);
128 if (isWorkerInstalled()) {
129 QAction *actAsAdminAction = actionCollection->addAction(QStringLiteral("act_as_admin"));
130 actAsAdminAction->setText(actionName());
131 actAsAdminAction->setIcon(QIcon::fromTheme(QStringLiteral("system-switch-user")));
132 actAsAdminAction->setCheckable(true);
133 actionCollection->setDefaultShortcut(actAsAdminAction, actionDefaultShortcut());
134
135 instance = new WorkerIntegration(dolphinMainWindow, actAsAdminAction);
136 }
137 }
138
139 QAction *WorkerIntegration::FriendAccess::actAsAdminAction()
140 {
141 return instance->m_actAsAdminAction;
142 }
143
144 void WorkerIntegration::toggleActAsAdmin()
145 {
146 auto dolphinMainWindow = static_cast<DolphinMainWindow *>(parent());
147 QUrl url = dolphinMainWindow->activeViewContainer()->urlNavigator()->locationUrl();
148
149 if (url.scheme() == QStringLiteral("admin")) {
150 url.setScheme(QStringLiteral("file"));
151 dolphinMainWindow->changeUrl(url);
152 return;
153 } else if (url.scheme() != QStringLiteral("file")) {
154 return;
155 }
156
157 bool risksAccepted = !KMessageBox::shouldBeShownContinue(warningDontShowAgainName);
158
159 if (!risksAccepted) {
160 KMessageDialog warningDialog{KMessageDialog::QuestionTwoActions, warningMessage(), dolphinMainWindow};
161 warningDialog.setCaption(i18nc("@title:window", "Risks of Acting as an Administrator"));
162 warningDialog.setIcon(QIcon::fromTheme(QStringLiteral("security-low")));
163 warningDialog.setButtons(KGuiItem{i18nc("@action:button", "I Understand and Accept These Risks"), QStringLiteral("data-warning")},
164 KStandardGuiItem::cancel());
165 warningDialog.setDontAskAgainText(i18nc("@option:check", "Do not warn me about these risks again"));
166
167 risksAccepted = warningDialog.exec() == KMessageDialog::PrimaryAction;
168
169 if (!risksAccepted) {
170 url.setScheme(QStringLiteral("file"));
171 updateActAsAdminAction(); // Uncheck the action
172 return;
173 }
174
175 if (warningDialog.isDontAskAgainChecked()) {
176 KMessageBox::saveDontShowAgainContinue(warningDontShowAgainName);
177 }
178 }
179
180 url.setScheme(QStringLiteral("admin"));
181 dolphinMainWindow->changeUrl(url);
182 }
183
184 void WorkerIntegration::updateActAsAdminAction()
185 {
186 if (instance) {
187 const QString currentUrlScheme = static_cast<DolphinMainWindow *>(instance->parent())->activeViewContainer()->url().scheme();
188 if (currentUrlScheme == QStringLiteral("file")) {
189 instance->m_actAsAdminAction->setEnabled(true);
190 instance->m_actAsAdminAction->setChecked(false);
191 } else if (currentUrlScheme == QStringLiteral("admin")) {
192 instance->m_actAsAdminAction->setEnabled(true);
193 instance->m_actAsAdminAction->setChecked(true);
194 } else {
195 instance->m_actAsAdminAction->setEnabled(false);
196 }
197 }
198 }
199
200 #include "moc_workerintegration.cpp"