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
27enum DialogType { ErrorDialog, WarningDialog };
28
29struct MessageBoxData {
30 QWidget *widget;
31 DialogType type = ErrorDialog;
32 QString msg;
33};
34
35class KDialogJobUiDelegatePrivate : public QObject
36{
37 Q_OBJECT
38public:
39 explicit KDialogJobUiDelegatePrivate(QObject *parent = nullptr);
40 ~KDialogJobUiDelegatePrivate() override;
41 void queuedMessageBox(QWidget *widget, DialogType type, const QString &msg);
42
43 QWidget *window;
44
45public Q_SLOTS:
46 void next();
47
48private:
49 bool running;
50 QQueue<QSharedPointer<MessageBoxData>> queue;
51};
52
53KDialogJobUiDelegatePrivate::KDialogJobUiDelegatePrivate(QObject *parent)
54 : QObject(parent)
55 , window(nullptr)
56 , running(false)
57{
58}
59
60KDialogJobUiDelegatePrivate::~KDialogJobUiDelegatePrivate()
61{
62 queue.clear();
63}
64
65void 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
94void 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
106KDialogJobUiDelegate::KDialogJobUiDelegate()
107 : KJobUiDelegate()
108 , d(new KDialogJobUiDelegatePrivate)
109{
110}
111
112KDialogJobUiDelegate::KDialogJobUiDelegate(KJobUiDelegate::Flags flags, QWidget *window)
113 : KJobUiDelegate(flags)
114 , d(new KDialogJobUiDelegatePrivate)
115{
116 d->window = window;
117}
118
119KDialogJobUiDelegate::~KDialogJobUiDelegate() = default;
120
121bool 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
133void KDialogJobUiDelegate::setWindow(QWidget *window)
134{
135 if (job()) {
136 KJobWidgets::setWindow(job: job(), widget: window);
137 }
138 d->window = window;
139}
140
141QWidget *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
151void KDialogJobUiDelegate::updateUserTimestamp(unsigned long time)
152{
153 KJobWidgets::updateUserTimestamp(job: job(), time);
154}
155
156unsigned long KDialogJobUiDelegate::userTimestamp() const
157{
158 return KJobWidgets::userTimestamp(job: job());
159}
160
161void KDialogJobUiDelegate::showErrorMessage()
162{
163 if (job()->error() != KJob::KilledJobError) {
164 d->queuedMessageBox(widget: window(), type: ErrorDialog, msg: job()->errorString());
165 }
166}
167
168void 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

source code of kjobwidgets/src/kdialogjobuidelegate.cpp