qtprogresscallback.cpp (5346B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "qtprogresscallback.h" 5 #include "qtutils.h" 6 7 #include "common/assert.h" 8 9 #include <QtCore/QCoreApplication> 10 #include <QtCore/QDebug> 11 #include <QtWidgets/QMessageBox> 12 #include <array> 13 14 QtModalProgressCallback::QtModalProgressCallback(QWidget* parent_widget, float show_delay) 15 : QObject(parent_widget), m_dialog(QString(), QString(), 0, 1, parent_widget), m_show_delay(show_delay) 16 { 17 m_dialog.setWindowTitle(tr("DuckStation")); 18 m_dialog.setMinimumSize(QSize(500, 0)); 19 m_dialog.setModal(parent_widget != nullptr); 20 m_dialog.setAutoClose(false); 21 m_dialog.setAutoReset(false); 22 connect(&m_dialog, &QProgressDialog::canceled, this, &QtModalProgressCallback::dialogCancelled); 23 checkForDelayedShow(); 24 } 25 26 QtModalProgressCallback::~QtModalProgressCallback() = default; 27 28 void QtModalProgressCallback::SetCancellable(bool cancellable) 29 { 30 if (m_cancellable == cancellable) 31 return; 32 33 ProgressCallback::SetCancellable(cancellable); 34 m_dialog.setCancelButtonText(cancellable ? tr("Cancel") : QString()); 35 } 36 37 void QtModalProgressCallback::SetTitle(const std::string_view title) 38 { 39 m_dialog.setWindowTitle(QtUtils::StringViewToQString(title)); 40 } 41 42 void QtModalProgressCallback::SetStatusText(const std::string_view text) 43 { 44 ProgressCallback::SetStatusText(text); 45 checkForDelayedShow(); 46 47 if (m_dialog.isVisible()) 48 m_dialog.setLabelText(QtUtils::StringViewToQString(text)); 49 } 50 51 void QtModalProgressCallback::SetProgressRange(u32 range) 52 { 53 ProgressCallback::SetProgressRange(range); 54 checkForDelayedShow(); 55 56 if (m_dialog.isVisible()) 57 m_dialog.setRange(0, m_progress_range); 58 } 59 60 void QtModalProgressCallback::SetProgressValue(u32 value) 61 { 62 ProgressCallback::SetProgressValue(value); 63 checkForDelayedShow(); 64 65 if (m_dialog.isVisible() && static_cast<u32>(m_dialog.value()) != m_progress_range) 66 m_dialog.setValue(m_progress_value); 67 68 QCoreApplication::processEvents(); 69 } 70 71 void QtModalProgressCallback::ModalError(const std::string_view message) 72 { 73 QMessageBox::critical(&m_dialog, tr("Error"), QtUtils::StringViewToQString(message)); 74 } 75 76 bool QtModalProgressCallback::ModalConfirmation(const std::string_view message) 77 { 78 return (QMessageBox::question(&m_dialog, tr("Question"), QtUtils::StringViewToQString(message), QMessageBox::Yes, 79 QMessageBox::No) == QMessageBox::Yes); 80 } 81 82 void QtModalProgressCallback::ModalInformation(const std::string_view message) 83 { 84 QMessageBox::information(&m_dialog, tr("Information"), QtUtils::StringViewToQString(message)); 85 } 86 87 void QtModalProgressCallback::dialogCancelled() 88 { 89 m_cancelled = true; 90 } 91 92 void QtModalProgressCallback::checkForDelayedShow() 93 { 94 if (m_dialog.isVisible()) 95 return; 96 97 if (m_show_timer.GetTimeSeconds() >= m_show_delay) 98 { 99 m_dialog.setRange(0, m_progress_range); 100 m_dialog.setValue(m_progress_value); 101 m_dialog.show(); 102 } 103 } 104 105 // NOTE: We deliberately don't set the thread parent, because otherwise we can't move it. 106 QtAsyncProgressThread::QtAsyncProgressThread(QWidget* parent) : QThread() 107 { 108 } 109 110 QtAsyncProgressThread::~QtAsyncProgressThread() = default; 111 112 bool QtAsyncProgressThread::IsCancelled() const 113 { 114 return isInterruptionRequested(); 115 } 116 117 void QtAsyncProgressThread::SetCancellable(bool cancellable) 118 { 119 if (m_cancellable == cancellable) 120 return; 121 122 ProgressCallback::SetCancellable(cancellable); 123 } 124 125 void QtAsyncProgressThread::SetTitle(const std::string_view title) 126 { 127 emit titleUpdated(QtUtils::StringViewToQString(title)); 128 } 129 130 void QtAsyncProgressThread::SetStatusText(const std::string_view text) 131 { 132 ProgressCallback::SetStatusText(text); 133 emit statusUpdated(QtUtils::StringViewToQString(text)); 134 } 135 136 void QtAsyncProgressThread::SetProgressRange(u32 range) 137 { 138 ProgressCallback::SetProgressRange(range); 139 emit progressUpdated(static_cast<int>(m_progress_value), static_cast<int>(m_progress_range)); 140 } 141 142 void QtAsyncProgressThread::SetProgressValue(u32 value) 143 { 144 ProgressCallback::SetProgressValue(value); 145 emit progressUpdated(static_cast<int>(m_progress_value), static_cast<int>(m_progress_range)); 146 } 147 148 void QtAsyncProgressThread::ModalError(const std::string_view message) 149 { 150 QMessageBox::critical(parentWidget(), tr("Error"), QtUtils::StringViewToQString(message)); 151 } 152 153 bool QtAsyncProgressThread::ModalConfirmation(const std::string_view message) 154 { 155 return (QMessageBox::question(parentWidget(), tr("Question"), QtUtils::StringViewToQString(message), QMessageBox::Yes, 156 QMessageBox::No) == QMessageBox::Yes); 157 } 158 159 void QtAsyncProgressThread::ModalInformation(const std::string_view message) 160 { 161 QMessageBox::information(parentWidget(), tr("Information"), QtUtils::StringViewToQString(message)); 162 } 163 164 void QtAsyncProgressThread::start() 165 { 166 Assert(!isRunning()); 167 168 QThread::start(); 169 moveToThread(this); 170 m_starting_thread = QThread::currentThread(); 171 m_start_semaphore.release(); 172 } 173 174 void QtAsyncProgressThread::join() 175 { 176 if (isRunning()) 177 QThread::wait(); 178 } 179 180 void QtAsyncProgressThread::run() 181 { 182 m_start_semaphore.acquire(); 183 emit threadStarting(); 184 runAsync(); 185 emit threadFinished(); 186 moveToThread(m_starting_thread); 187 } 188 189 QWidget* QtAsyncProgressThread::parentWidget() const 190 { 191 return qobject_cast<QWidget*>(parent()); 192 }