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