File indexing completed on 2025-01-26 04:08:03

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_delayed_save_dialog.h"
0008 #include "ui_kis_delayed_save_dialog.h"
0009 
0010 #include <QElapsedTimer>
0011 #include <QThread>
0012 #include <QTimer>
0013 #include <QtGlobal>
0014 
0015 #include "kis_debug.h"
0016 #include "kis_image.h"
0017 #include "kis_composite_progress_proxy.h"
0018 
0019 struct Q_DECL_HIDDEN KisDelayedSaveDialog::Private {
0020     Private(KisImageSP _image, int _busyWait, Type _type) : image(_image), busyWait(_busyWait), type(_type) {}
0021 
0022     KisImageSP image;
0023     QTimer updateTimer;
0024     int busyWait;
0025 
0026     bool checkImageIdle() {
0027         const bool allowLocked = type != SaveDialog;
0028         return image->isIdle(allowLocked);
0029     }
0030 
0031     Type type;
0032 };
0033 
0034 class Q_DECL_HIDDEN WdgDelayedSaveDialog : public QWidget, public Ui::KisDelayedSaveDialog
0035 {
0036     Q_OBJECT
0037 
0038 public:
0039     WdgDelayedSaveDialog(QWidget *parent = nullptr)
0040         : QWidget(parent)
0041     {
0042         setupUi(this);
0043     }
0044 };
0045 
0046 KisDelayedSaveDialog::KisDelayedSaveDialog(KisImageSP image, Type type, int busyWait, QWidget *parent)
0047     : KoDialog(parent)
0048     , ui(new WdgDelayedSaveDialog())
0049     , m_d(new Private(image, busyWait, type))
0050 {
0051     KIS_ASSERT_RECOVER_NOOP(image);
0052 
0053     setMainWidget(ui);
0054 
0055     if (type == SaveDialog) {
0056         setButtons(KoDialog::Ok | KoDialog::Cancel | KoDialog::User1);
0057         setButtonText(KoDialog::Ok, i18n("Save without waiting"));
0058         setButtonText(KoDialog::Cancel, i18n("Cancel operation and save"));
0059         setButtonText(KoDialog::User1, i18n("Close, do not save"));
0060 
0061         connect(this, &KoDialog::okClicked, this, &KisDelayedSaveDialog::slotIgnoreRequested);
0062 
0063         connect(this, &KoDialog::cancelClicked, this, &KisDelayedSaveDialog::slotCancelRequested);
0064 
0065         connect(this, &KoDialog::user1Clicked, this, &KisDelayedSaveDialog::reject);
0066     } else if (type == GeneralDialog) {
0067         setButtons(KoDialog::Cancel);
0068         connect(this, &KoDialog::cancelClicked, &KisDelayedSaveDialog::reject);
0069     } else { // type == ForcedDialog, disable closing
0070         setButtons(KoDialog::None);
0071         setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint);
0072     }
0073 
0074     connect(&m_d->updateTimer, &QTimer::timeout, this, &KisDelayedSaveDialog::slotTimerTimeout);
0075 
0076     m_d->image->compositeProgressProxy()->addProxy(ui->progressBar);
0077 
0078     resize(sizeHint());
0079 }
0080 
0081 KisDelayedSaveDialog::~KisDelayedSaveDialog()
0082 {
0083     m_d->image->compositeProgressProxy()->removeProxy(ui->progressBar);
0084     delete ui;
0085 }
0086 
0087 void KisDelayedSaveDialog::blockIfImageIsBusy()
0088 {
0089     if (m_d->checkImageIdle()) {
0090         setResult(Accepted);
0091         return;
0092     }
0093 
0094     m_d->image->requestStrokeEnd();
0095 
0096     QElapsedTimer t;
0097     t.start();
0098 
0099     while (t.elapsed() < m_d->busyWait) {
0100         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
0101 
0102         if (m_d->checkImageIdle()) {
0103             setResult(Accepted);
0104             return;
0105         }
0106 
0107         QThread::yieldCurrentThread();
0108     }
0109 
0110     m_d->updateTimer.start(200);
0111     exec();
0112     m_d->updateTimer.stop();
0113 }
0114 
0115 void KisDelayedSaveDialog::slotTimerTimeout()
0116 {
0117     if (m_d->checkImageIdle()) {
0118         accept();
0119     }
0120 }
0121 
0122 void KisDelayedSaveDialog::slotCancelRequested()
0123 {
0124     m_d->image->requestStrokeCancellation();
0125 }
0126 
0127 void KisDelayedSaveDialog::slotIgnoreRequested()
0128 {
0129     done(Ignored);
0130 }
0131 
0132 #include "kis_delayed_save_dialog.moc"