File indexing completed on 2024-09-15 12:01:07
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org> 0004 SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2006, 2007 Kevin Ottens <ervin@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "kdialogjobuidelegate.h" 0011 0012 #include <QPointer> 0013 #include <QQueue> 0014 #include <QWidget> 0015 0016 #include <KJob> 0017 #include <KMessageBox> 0018 #include <kjobwidgets.h> 0019 0020 #include <config-kjobwidgets.h> 0021 #if HAVE_X11 0022 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0023 #include <private/qtx11extras_p.h> 0024 #else 0025 #include <QX11Info> 0026 #endif 0027 #endif 0028 0029 enum DialogType { ErrorDialog, WarningDialog }; 0030 0031 struct MessageBoxData { 0032 QWidget *widget; 0033 DialogType type = ErrorDialog; 0034 QString msg; 0035 }; 0036 0037 class KDialogJobUiDelegatePrivate : public QObject 0038 { 0039 Q_OBJECT 0040 public: 0041 explicit KDialogJobUiDelegatePrivate(QObject *parent = nullptr); 0042 ~KDialogJobUiDelegatePrivate() override; 0043 void queuedMessageBox(QWidget *widget, DialogType type, const QString &msg); 0044 0045 QWidget *window; 0046 0047 public Q_SLOTS: 0048 void next(); 0049 0050 private: 0051 bool running; 0052 QQueue<QSharedPointer<MessageBoxData>> queue; 0053 }; 0054 0055 KDialogJobUiDelegatePrivate::KDialogJobUiDelegatePrivate(QObject *parent) 0056 : QObject(parent) 0057 , window(nullptr) 0058 , running(false) 0059 { 0060 } 0061 0062 KDialogJobUiDelegatePrivate::~KDialogJobUiDelegatePrivate() 0063 { 0064 queue.clear(); 0065 } 0066 0067 void KDialogJobUiDelegatePrivate::next() 0068 { 0069 if (queue.isEmpty()) { 0070 running = false; 0071 return; 0072 } 0073 0074 QSharedPointer<MessageBoxData> data = queue.dequeue(); 0075 0076 // kmessagebox starts a new event loop which can cause this to get deleted 0077 // https://bugs.kde.org/show_bug.cgi?id=356321#c16 0078 QPointer<KDialogJobUiDelegatePrivate> thisGuard(this); 0079 0080 switch (data->type) { 0081 case ErrorDialog: 0082 KMessageBox::error(data->widget, data->msg); 0083 break; 0084 case WarningDialog: 0085 KMessageBox::information(data->widget, data->msg); 0086 break; 0087 }; 0088 0089 if (!thisGuard) { 0090 return; 0091 } 0092 0093 QMetaObject::invokeMethod(this, &KDialogJobUiDelegatePrivate::next, Qt::QueuedConnection); 0094 } 0095 0096 void KDialogJobUiDelegatePrivate::queuedMessageBox(QWidget *widget, DialogType type, const QString &msg) 0097 { 0098 QSharedPointer<MessageBoxData> data(new MessageBoxData{widget, type, msg}); 0099 0100 queue.enqueue(data); 0101 0102 if (!running) { 0103 running = true; 0104 QMetaObject::invokeMethod(this, &KDialogJobUiDelegatePrivate::next, Qt::QueuedConnection); 0105 } 0106 } 0107 0108 KDialogJobUiDelegate::KDialogJobUiDelegate() 0109 : KJobUiDelegate() 0110 , d(new KDialogJobUiDelegatePrivate) 0111 { 0112 } 0113 0114 KDialogJobUiDelegate::KDialogJobUiDelegate(KJobUiDelegate::Flags flags, QWidget *window) 0115 : KJobUiDelegate(flags) 0116 , d(new KDialogJobUiDelegatePrivate) 0117 { 0118 d->window = window; 0119 } 0120 0121 KDialogJobUiDelegate::~KDialogJobUiDelegate() = default; 0122 0123 bool KDialogJobUiDelegate::setJob(KJob *job) 0124 { 0125 bool ret = KJobUiDelegate::setJob(job); 0126 #if HAVE_X11 0127 if (ret) { 0128 unsigned long time = QX11Info::appUserTime(); 0129 KJobWidgets::updateUserTimestamp(job, time); 0130 } 0131 #endif 0132 return ret; 0133 } 0134 0135 void KDialogJobUiDelegate::setWindow(QWidget *window) 0136 { 0137 if (job()) { 0138 KJobWidgets::setWindow(job(), window); 0139 } 0140 d->window = window; 0141 } 0142 0143 QWidget *KDialogJobUiDelegate::window() const 0144 { 0145 if (d->window) { 0146 return d->window; 0147 } else if (job()) { 0148 return KJobWidgets::window(job()); 0149 } 0150 return nullptr; 0151 } 0152 0153 void KDialogJobUiDelegate::updateUserTimestamp(unsigned long time) 0154 { 0155 KJobWidgets::updateUserTimestamp(job(), time); 0156 } 0157 0158 unsigned long KDialogJobUiDelegate::userTimestamp() const 0159 { 0160 return KJobWidgets::userTimestamp(job()); 0161 } 0162 0163 void KDialogJobUiDelegate::showErrorMessage() 0164 { 0165 if (job()->error() != KJob::KilledJobError) { 0166 d->queuedMessageBox(window(), ErrorDialog, job()->errorString()); 0167 } 0168 } 0169 0170 void KDialogJobUiDelegate::slotWarning(KJob * /*job*/, const QString &plain, const QString & /*rich*/) 0171 { 0172 if (isAutoWarningHandlingEnabled()) { 0173 d->queuedMessageBox(window(), WarningDialog, plain); 0174 } 0175 } 0176 0177 #include "kdialogjobuidelegate.moc" 0178 #include "moc_kdialogjobuidelegate.cpp"