/* This file is part of the KDE libraries SPDX-FileCopyrightText: 2000 Stephan Kulow SPDX-FileCopyrightText: 2000 David Faure SPDX-FileCopyrightText: 2006, 2007 Kevin Ottens SPDX-License-Identifier: LGPL-2.0-or-later */ #include "kdialogjobuidelegate.h" #include #include #include #include #include #include #include #if WITH_X11 #include #endif enum DialogType { ErrorDialog, WarningDialog }; struct MessageBoxData { QWidget *widget; DialogType type = ErrorDialog; QString msg; }; class KDialogJobUiDelegatePrivate : public QObject { Q_OBJECT public: explicit KDialogJobUiDelegatePrivate(QObject *parent = nullptr); ~KDialogJobUiDelegatePrivate() override; void queuedMessageBox(QWidget *widget, DialogType type, const QString &msg); QWidget *window; public Q_SLOTS: void next(); private: bool running; QQueue> queue; }; KDialogJobUiDelegatePrivate::KDialogJobUiDelegatePrivate(QObject *parent) : QObject(parent) , window(nullptr) , running(false) { } KDialogJobUiDelegatePrivate::~KDialogJobUiDelegatePrivate() { queue.clear(); } void KDialogJobUiDelegatePrivate::next() { if (queue.isEmpty()) { running = false; return; } QSharedPointer data = queue.dequeue(); // kmessagebox starts a new event loop which can cause this to get deleted // https://bugs.kde.org/show_bug.cgi?id=356321#c16 QPointer thisGuard(this); switch (data->type) { case ErrorDialog: KMessageBox::error(data->widget, data->msg); break; case WarningDialog: KMessageBox::information(data->widget, data->msg); break; }; if (!thisGuard) { return; } QMetaObject::invokeMethod(this, &KDialogJobUiDelegatePrivate::next, Qt::QueuedConnection); } void KDialogJobUiDelegatePrivate::queuedMessageBox(QWidget *widget, DialogType type, const QString &msg) { QSharedPointer data(new MessageBoxData{widget, type, msg}); queue.enqueue(data); if (!running) { running = true; QMetaObject::invokeMethod(this, &KDialogJobUiDelegatePrivate::next, Qt::QueuedConnection); } } KDialogJobUiDelegate::KDialogJobUiDelegate() : KJobUiDelegate() , d(new KDialogJobUiDelegatePrivate) { } KDialogJobUiDelegate::KDialogJobUiDelegate(KJobUiDelegate::Flags flags, QWidget *window) : KJobUiDelegate(flags) , d(new KDialogJobUiDelegatePrivate) { d->window = window; } KDialogJobUiDelegate::~KDialogJobUiDelegate() = default; bool KDialogJobUiDelegate::setJob(KJob *job) { bool ret = KJobUiDelegate::setJob(job); #if WITH_X11 if (ret) { unsigned long time = QX11Info::appUserTime(); KJobWidgets::updateUserTimestamp(job, time); } #endif return ret; } void KDialogJobUiDelegate::setWindow(QWidget *window) { if (job()) { KJobWidgets::setWindow(job(), window); } d->window = window; } QWidget *KDialogJobUiDelegate::window() const { if (d->window) { return d->window; } else if (job()) { return KJobWidgets::window(job()); } return nullptr; } void KDialogJobUiDelegate::updateUserTimestamp(unsigned long time) { KJobWidgets::updateUserTimestamp(job(), time); } unsigned long KDialogJobUiDelegate::userTimestamp() const { return KJobWidgets::userTimestamp(job()); } void KDialogJobUiDelegate::showErrorMessage() { if (job()->error() != KJob::KilledJobError) { d->queuedMessageBox(window(), ErrorDialog, job()->errorString()); } } void KDialogJobUiDelegate::slotWarning(KJob * /*job*/, const QString &message) { if (isAutoWarningHandlingEnabled()) { d->queuedMessageBox(window(), WarningDialog, message); } } #include "kdialogjobuidelegate.moc" #include "moc_kdialogjobuidelegate.cpp"