1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org> |
4 | SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> |
5 | SPDX-FileCopyrightText: 2006, 2007 Kevin Ottens <ervin@kde.org> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.0-or-later |
8 | */ |
9 | |
10 | #include "kdialogjobuidelegate.h" |
11 | |
12 | #include <QPointer> |
13 | #include <QQueue> |
14 | #include <QWidget> |
15 | |
16 | #include <KJob> |
17 | #include <KJobWidgets> |
18 | #include <KMessageBox> |
19 | |
20 | #if __has_include(<private/qtx11extras_p.h>) |
21 | #include <private/qtx11extras_p.h> |
22 | #define HAVE_X11 1 |
23 | #else |
24 | #define HAVE_X11 0 |
25 | #endif |
26 | |
27 | enum DialogType { ErrorDialog, WarningDialog }; |
28 | |
29 | struct MessageBoxData { |
30 | QWidget *widget; |
31 | DialogType type = ErrorDialog; |
32 | QString msg; |
33 | }; |
34 | |
35 | class KDialogJobUiDelegatePrivate : public QObject |
36 | { |
37 | Q_OBJECT |
38 | public: |
39 | explicit KDialogJobUiDelegatePrivate(QObject *parent = nullptr); |
40 | ~KDialogJobUiDelegatePrivate() override; |
41 | void queuedMessageBox(QWidget *widget, DialogType type, const QString &msg); |
42 | |
43 | QWidget *window; |
44 | |
45 | public Q_SLOTS: |
46 | void next(); |
47 | |
48 | private: |
49 | bool running; |
50 | QQueue<QSharedPointer<MessageBoxData>> queue; |
51 | }; |
52 | |
53 | KDialogJobUiDelegatePrivate::KDialogJobUiDelegatePrivate(QObject *parent) |
54 | : QObject(parent) |
55 | , window(nullptr) |
56 | , running(false) |
57 | { |
58 | } |
59 | |
60 | KDialogJobUiDelegatePrivate::~KDialogJobUiDelegatePrivate() |
61 | { |
62 | queue.clear(); |
63 | } |
64 | |
65 | void KDialogJobUiDelegatePrivate::next() |
66 | { |
67 | if (queue.isEmpty()) { |
68 | running = false; |
69 | return; |
70 | } |
71 | |
72 | QSharedPointer<MessageBoxData> data = queue.dequeue(); |
73 | |
74 | // kmessagebox starts a new event loop which can cause this to get deleted |
75 | // https://bugs.kde.org/show_bug.cgi?id=356321#c16 |
76 | QPointer<KDialogJobUiDelegatePrivate> thisGuard(this); |
77 | |
78 | switch (data->type) { |
79 | case ErrorDialog: |
80 | KMessageBox::error(parent: data->widget, text: data->msg); |
81 | break; |
82 | case WarningDialog: |
83 | KMessageBox::information(parent: data->widget, text: data->msg); |
84 | break; |
85 | }; |
86 | |
87 | if (!thisGuard) { |
88 | return; |
89 | } |
90 | |
91 | QMetaObject::invokeMethod(object: this, function: &KDialogJobUiDelegatePrivate::next, type: Qt::QueuedConnection); |
92 | } |
93 | |
94 | void KDialogJobUiDelegatePrivate::queuedMessageBox(QWidget *widget, DialogType type, const QString &msg) |
95 | { |
96 | QSharedPointer<MessageBoxData> data(new MessageBoxData{.widget: widget, .type: type, .msg: msg}); |
97 | |
98 | queue.enqueue(t: data); |
99 | |
100 | if (!running) { |
101 | running = true; |
102 | QMetaObject::invokeMethod(object: this, function: &KDialogJobUiDelegatePrivate::next, type: Qt::QueuedConnection); |
103 | } |
104 | } |
105 | |
106 | KDialogJobUiDelegate::KDialogJobUiDelegate() |
107 | : KJobUiDelegate() |
108 | , d(new KDialogJobUiDelegatePrivate) |
109 | { |
110 | } |
111 | |
112 | KDialogJobUiDelegate::KDialogJobUiDelegate(KJobUiDelegate::Flags flags, QWidget *window) |
113 | : KJobUiDelegate(flags) |
114 | , d(new KDialogJobUiDelegatePrivate) |
115 | { |
116 | d->window = window; |
117 | } |
118 | |
119 | KDialogJobUiDelegate::~KDialogJobUiDelegate() = default; |
120 | |
121 | bool KDialogJobUiDelegate::setJob(KJob *job) |
122 | { |
123 | bool ret = KJobUiDelegate::setJob(job); |
124 | #if HAVE_X11 |
125 | if (ret) { |
126 | unsigned long time = QX11Info::appUserTime(); |
127 | KJobWidgets::updateUserTimestamp(job, time); |
128 | } |
129 | #endif |
130 | return ret; |
131 | } |
132 | |
133 | void KDialogJobUiDelegate::setWindow(QWidget *window) |
134 | { |
135 | if (job()) { |
136 | KJobWidgets::setWindow(job: job(), widget: window); |
137 | } |
138 | d->window = window; |
139 | } |
140 | |
141 | QWidget *KDialogJobUiDelegate::window() const |
142 | { |
143 | if (d->window) { |
144 | return d->window; |
145 | } else if (job()) { |
146 | return KJobWidgets::window(job: job()); |
147 | } |
148 | return nullptr; |
149 | } |
150 | |
151 | void KDialogJobUiDelegate::updateUserTimestamp(unsigned long time) |
152 | { |
153 | KJobWidgets::updateUserTimestamp(job: job(), time); |
154 | } |
155 | |
156 | unsigned long KDialogJobUiDelegate::userTimestamp() const |
157 | { |
158 | return KJobWidgets::userTimestamp(job: job()); |
159 | } |
160 | |
161 | void KDialogJobUiDelegate::showErrorMessage() |
162 | { |
163 | if (job()->error() != KJob::KilledJobError) { |
164 | d->queuedMessageBox(widget: window(), type: ErrorDialog, msg: job()->errorString()); |
165 | } |
166 | } |
167 | |
168 | void KDialogJobUiDelegate::slotWarning(KJob * /*job*/, const QString &message) |
169 | { |
170 | if (isAutoWarningHandlingEnabled()) { |
171 | d->queuedMessageBox(widget: window(), type: WarningDialog, msg: message); |
172 | } |
173 | } |
174 | |
175 | #include "kdialogjobuidelegate.moc" |
176 | #include "moc_kdialogjobuidelegate.cpp" |
177 | |