KIO

widgetsuntrustedprogramhandler.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "widgetsuntrustedprogramhandler.h"
9
10#include <KIconLoader>
11#include <KJob>
12#include <KJobWidgets>
13#include <KLocalizedString>
14#include <KStandardGuiItem>
15
16#include <QApplication>
17#include <QDialog>
18#include <QDialogButtonBox>
19#include <QHBoxLayout>
20#include <QLabel>
21#include <QPlainTextEdit>
22#include <QPushButton>
23#include <QScreen>
24#include <QStyle>
25#include <QVBoxLayout>
26
27class KIO::WidgetsUntrustedProgramHandlerPrivate
28{
29public:
30 QWidget *m_parentWidget = nullptr;
31};
32
33KIO::WidgetsUntrustedProgramHandler::WidgetsUntrustedProgramHandler(QObject *parent)
34 : KIO::UntrustedProgramHandlerInterface(parent)
35 , d(std::make_unique<WidgetsUntrustedProgramHandlerPrivate>())
36{
37}
38
39KIO::WidgetsUntrustedProgramHandler::~WidgetsUntrustedProgramHandler()
40{
41}
42
43// Simple QDialog that resizes the given text edit after being shown to more
44// or less fit the enclosed text.
45class SecureMessageDialog : public QDialog
46{
47 Q_OBJECT
48public:
49 explicit SecureMessageDialog(QWidget *parent)
50 : QDialog(parent)
51 , m_textEdit(nullptr)
52 {
53 }
54
55 void setTextEdit(QPlainTextEdit *textEdit)
56 {
57 m_textEdit = textEdit;
58 }
59
60protected:
61 void showEvent(QShowEvent *e) override
62 {
63 if (e->spontaneous()) {
64 return;
65 }
66
67 // Now that we're shown, use our width to calculate a good
68 // bounding box for the text, and resize m_textEdit appropriately.
70
71 if (!m_textEdit) {
72 return;
73 }
74
75 QSize fudge(20, 24); // About what it sounds like :-/
76
77 // Form rect with a lot of height for bounding. Use no more than
78 // 5 lines.
79 QRect curRect(m_textEdit->rect());
80 QFontMetrics metrics(fontMetrics());
81 curRect.setHeight(5 * metrics.lineSpacing());
82 curRect.setWidth(qMax(curRect.width(), 300)); // At least 300 pixels ok?
83
84 QString text(m_textEdit->toPlainText());
85 curRect = metrics.boundingRect(curRect, Qt::TextWordWrap | Qt::TextSingleLine, text);
86
87 // Scroll bars interfere. If we don't think there's enough room, enable
88 // the vertical scrollbar however.
89 m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
90 if (curRect.height() < m_textEdit->height()) { // then we've got room
91 m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
92 m_textEdit->setMaximumHeight(curRect.height() + fudge.height());
93 }
94
95 m_textEdit->setMinimumSize(curRect.size() + fudge);
96 m_textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
97 }
98
99private:
100 QPlainTextEdit *m_textEdit;
101};
102
103QDialog *KIO::WidgetsUntrustedProgramHandler::createDialog(QWidget *parentWidget, const QString &programName)
104{
105 SecureMessageDialog *baseDialog = new SecureMessageDialog(parentWidget);
106 baseDialog->setWindowTitle(i18nc("Warning about executing unknown program", "Warning"));
107
108 QVBoxLayout *topLayout = new QVBoxLayout(baseDialog);
109
110 // Dialog will have explanatory text with a disabled lineedit with the
111 // Exec= to make it visually distinct.
112 QWidget *baseWidget = new QWidget(baseDialog);
113 QHBoxLayout *mainLayout = new QHBoxLayout(baseWidget);
114
115 QLabel *iconLabel = new QLabel(baseWidget);
116 const QIcon icon = baseDialog->style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, baseDialog);
117 const QPixmap warningIcon(icon.pixmap(KIconLoader::SizeHuge));
118 mainLayout->addWidget(iconLabel);
119 iconLabel->setPixmap(warningIcon);
120
121 QVBoxLayout *contentLayout = new QVBoxLayout;
122 QString warningMessage = i18nc("program name follows in a line edit below", "This will start the program:");
123
124 QLabel *message = new QLabel(warningMessage, baseWidget);
125 contentLayout->addWidget(message);
126
127 QPlainTextEdit *textEdit = new QPlainTextEdit(baseWidget);
128 textEdit->setPlainText(programName);
129 textEdit->setReadOnly(true);
130 contentLayout->addWidget(textEdit);
131
132 QLabel *footerLabel = new QLabel(i18n("If you do not trust this program, click Cancel"));
133 contentLayout->addWidget(footerLabel);
134 contentLayout->addStretch(0); // Don't allow the text edit to expand
135
136 mainLayout->addLayout(contentLayout);
137
138 topLayout->addWidget(baseWidget);
139 baseDialog->setTextEdit(textEdit);
140
141 QDialogButtonBox *buttonBox = new QDialogButtonBox(baseDialog);
144 buttonBox->button(QDialogButtonBox::Cancel)->setDefault(true);
148 topLayout->addWidget(buttonBox);
149
150 // Constrain maximum size. Minimum size set in
151 // the dialog's show event.
152 const QSize screenSize = baseDialog->screen()->size();
153 baseDialog->resize(screenSize.width() / 4, 50);
154 baseDialog->setMaximumHeight(screenSize.height() / 3);
155 baseDialog->setMaximumWidth(screenSize.width() / 10 * 8);
156
158 return baseDialog;
159}
160
161void KIO::WidgetsUntrustedProgramHandler::showUntrustedProgramWarning(KJob *job, const QString &programName)
162{
163 QWidget *parentWidget = nullptr;
164
165 if (job) {
166 parentWidget = KJobWidgets::window(job);
167 }
168
169 if (!parentWidget) {
170 parentWidget = d->m_parentWidget;
171 }
172
173 if (!parentWidget) {
174 parentWidget = qApp->activeWindow();
175 }
176
177 QDialog *dialog = createDialog(parentWidget, programName);
178 connect(dialog, &QDialog::accepted, this, [this]() {
179 Q_EMIT result(true);
180 });
181 connect(dialog, &QDialog::rejected, this, [this]() {
182 Q_EMIT result(false);
183 });
184 dialog->show();
185}
186
187bool KIO::WidgetsUntrustedProgramHandler::execUntrustedProgramWarning(QWidget *window, const QString &programName)
188{
189 QDialog *dialog = createDialog(window, programName);
190 return dialog->exec() == QDialog::Accepted;
191}
192
193void KIO::WidgetsUntrustedProgramHandler::setWindow(QWidget *window)
194{
195 d->m_parentWidget = window;
196}
197
198#include "moc_widgetsuntrustedprogramhandler.cpp"
199#include "widgetsuntrustedprogramhandler.moc"
static void assign(QPushButton *button, const KGuiItem &item)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
A namespace for KIO globals.
QWidget * window(QObject *job)
KGuiItem cont()
void addLayout(QLayout *layout, int stretch)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
virtual void accept()
void accepted()
virtual int exec()
virtual void reject()
void rejected()
virtual void showEvent(QShowEvent *event) override
QPushButton * button(StandardButton which) const const
void setStandardButtons(StandardButtons buttons)
bool spontaneous() const const
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
void setPixmap(const QPixmap &)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setReadOnly(bool ro)
void setPlainText(const QString &text)
void setDefault(bool)
int height() const const
int width() const const
SP_MessageBoxWarning
virtual QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const const=0
ScrollBarAlwaysOff
TextWordWrap
WA_DeleteOnClose
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setMaximumHeight(int maxh)
void setMaximumWidth(int maxw)
QScreen * screen() const const
void setAttribute(Qt::WidgetAttribute attribute, bool on)
void setFocus()
void show()
void resize(const QSize &)
QStyle * style() const const
void setWindowTitle(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:52 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.