File indexing completed on 2024-04-14 03:54:03

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"