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