2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@kde.org>
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8 #include "workerintegration.h"
10 #include "config-dolphin.h"
11 #include "dolphinmainwindow.h"
12 #include "dolphinpackageinstaller.h"
13 #include "dolphinviewcontainer.h"
15 #include <KActionCollection>
16 #include <KLocalizedString>
17 #include <KMessageBox>
18 #include <KMessageDialog>
19 #include <KProtocolInfo>
25 using namespace Admin
;
27 /** Free file-local functions */
30 /** @returns the translated name of the actAsAdminAction. */
33 return i18nc("@action:inmenu", "Act as Administrator");
36 /** @returns the default keyboard shortcut of the actAsAdminAction. */
37 QKeySequence
actionDefaultShortcut()
39 return Qt::CTRL
| Qt::SHIFT
| Qt::ALT
| Qt::Key_A
;
42 /** @returns whether any worker for the protocol "admin" is available. */
43 bool isWorkerInstalled()
45 return KProtocolInfo::isKnownProtocol(QStringLiteral("admin"));
49 void Admin::guideUserTowardsInstallingAdminWorker()
51 if (!isWorkerInstalled()) {
52 std::cout
<< qPrintable(
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
)));
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
) {
65 std::cout
<< qPrintable(job
->errorString()) << std::endl
;
69 adminWorkerInstaller
.exec();
73 void Admin::guideUserTowardsUsingAdminWorker()
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>"));
79 KMessageBox::information(
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>",
88 actionDefaultShortcut().toString(QKeySequence::NativeText
)),
89 i18nc("@title:window", "How to Administrate"),
91 KMessageBox::WindowModal
);
94 QString
Admin::warningMessage()
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>");
107 /** The only WorkerIntegration object that is ever constructed. It is only ever accessed directly from within this file. */
108 WorkerIntegration
*instance
= nullptr;
111 WorkerIntegration::WorkerIntegration(DolphinMainWindow
*parent
, QAction
*actAsAdminAction
)
113 , m_actAsAdminAction
{actAsAdminAction
}
116 Q_CHECK_PTR(actAsAdminAction
);
118 connect(parent
, &DolphinMainWindow::urlChanged
, this, &WorkerIntegration::updateActAsAdminAction
);
120 connect(actAsAdminAction
, &QAction::triggered
, this, &WorkerIntegration::toggleActAsAdmin
);
123 void WorkerIntegration::createActAsAdminAction(KActionCollection
*actionCollection
, DolphinMainWindow
*dolphinMainWindow
)
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());
135 instance
= new WorkerIntegration(dolphinMainWindow
, actAsAdminAction
);
139 QAction
*WorkerIntegration::FriendAccess::actAsAdminAction()
141 return instance
->m_actAsAdminAction
;
144 void WorkerIntegration::toggleActAsAdmin()
146 auto dolphinMainWindow
= static_cast<DolphinMainWindow
*>(parent());
147 QUrl url
= dolphinMainWindow
->activeViewContainer()->urlNavigator()->locationUrl();
149 if (url
.scheme() == QStringLiteral("admin")) {
150 url
.setScheme(QStringLiteral("file"));
151 dolphinMainWindow
->changeUrl(url
);
153 } else if (url
.scheme() != QStringLiteral("file")) {
157 bool risksAccepted
= !KMessageBox::shouldBeShownContinue(warningDontShowAgainName
);
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"));
167 risksAccepted
= warningDialog
.exec() == KMessageDialog::PrimaryAction
;
169 if (!risksAccepted
) {
170 url
.setScheme(QStringLiteral("file"));
171 updateActAsAdminAction(); // Uncheck the action
175 if (warningDialog
.isDontAskAgainChecked()) {
176 KMessageBox::saveDontShowAgainContinue(warningDontShowAgainName
);
180 url
.setScheme(QStringLiteral("admin"));
181 dolphinMainWindow
->changeUrl(url
);
184 void WorkerIntegration::updateActAsAdminAction()
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);
195 instance
->m_actAsAdminAction
->setEnabled(false);
200 #include "moc_workerintegration.cpp"