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

source code of kjobwidgets/src/kdialogjobuidelegate.cpp