File indexing completed on 2024-04-28 11:22:20
0001 /* KStars Asynchronous Message Box Implementation for Desktop/Android and EkosLive 0002 Based on QMessageBox. 0003 0004 SPDX-FileCopyrightText: 2019 Jasem Mutlaq <mutlaqja@ikarustech.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "ksmessagebox.h" 0010 #include "config-kstars.h" 0011 #include "Options.h" 0012 0013 #ifdef KSTARS_LITE 0014 #include "kstarslite.h" 0015 #else 0016 #include "kstars.h" 0017 #endif 0018 0019 #include <QPushButton> 0020 #include <QCheckBox> 0021 #include <QLayout> 0022 #include <QSpacerItem> 0023 #include <QLabel> 0024 0025 KSMessageBox * KSMessageBox::m_Instance = nullptr; 0026 0027 KSMessageBox * KSMessageBox::Instance() 0028 { 0029 if (!m_Instance) 0030 m_Instance = new KSMessageBox(); 0031 0032 return m_Instance; 0033 } 0034 0035 KSMessageBox::KSMessageBox() : QMessageBox() 0036 { 0037 setDefaultButton(StandardButton::Ok); 0038 setIcon(QMessageBox::Information); 0039 setObjectName("KSMessageBox"); 0040 0041 setWindowFlags(Qt::WindowStaysOnTopHint); 0042 0043 m_ProgressTimer.setInterval(1000); 0044 m_ProgressTimer.setSingleShot(false); 0045 connect(&m_ProgressTimer, &QTimer::timeout, this, &KSMessageBox::timerTick); 0046 0047 connect(this, &KSMessageBox::rejected, [this]() 0048 { 0049 m_ProgressTimer.stop(); 0050 emit newMessage(QJsonObject()); 0051 }); 0052 0053 connect(this, &KSMessageBox::accepted, [this]() 0054 { 0055 m_ProgressTimer.stop(); 0056 emit newMessage(QJsonObject()); 0057 }); 0058 } 0059 0060 void KSMessageBox::error(const QString &message, const QString &title, quint32 timeout) 0061 { 0062 #ifdef KSTARS_LITE 0063 Q_UNUSED(title); 0064 KStarsLite::Instance()->notificationMessage(message); 0065 #else 0066 //KMessageBox::error(nullptr, message, title); 0067 reset(); 0068 0069 addOKButton(); 0070 setIcon(QMessageBox::Critical); 0071 setText(message); 0072 setWindowTitle(title); 0073 0074 setupTimeout(timeout); 0075 open(); 0076 0077 emit newMessage(createMessageObject()); 0078 #endif 0079 } 0080 0081 void KSMessageBox::sorry(const QString &message, const QString &title, quint32 timeout) 0082 { 0083 #ifdef KSTARS_LITE 0084 Q_UNUSED(title); 0085 KStarsLite::Instance()->notificationMessage(message); 0086 #else 0087 //KSNotification::sorry(message, title); 0088 reset(); 0089 0090 addOKButton(); 0091 setIcon(QMessageBox::Warning); 0092 setText(message); 0093 setWindowTitle(title); 0094 0095 setupTimeout(timeout); 0096 open(); 0097 0098 emit newMessage(createMessageObject()); 0099 #endif 0100 } 0101 0102 void KSMessageBox::info(const QString &message, const QString &title, quint32 timeout) 0103 { 0104 #ifdef KSTARS_LITE 0105 Q_UNUSED(title); 0106 KStarsLite::Instance()->notificationMessage(message); 0107 #else 0108 //KMessageBox::information(nullptr, message, title); 0109 reset(); 0110 0111 addOKButton(); 0112 setIcon(QMessageBox::Information); 0113 setText(message); 0114 setWindowTitle(title); 0115 0116 setupTimeout(timeout); 0117 open(); 0118 0119 emit newMessage(createMessageObject()); 0120 0121 0122 #endif 0123 } 0124 0125 void KSMessageBox::setupTimeout(quint32 timeout) 0126 { 0127 m_Timeout = timeout; 0128 if (m_Timeout == 0) 0129 return; 0130 0131 m_ProgressLabel = new QLabel(this); 0132 m_ProgressLabel->setText(i18n("Auto close in ...")); 0133 0134 m_ProgressIndicator = new QRoundProgressBar(this); 0135 m_ProgressIndicator->setDecimals(0); 0136 m_ProgressIndicator->setFormat("%v"); 0137 m_ProgressIndicator->setBarStyle(QRoundProgressBar::StyleLine); 0138 m_ProgressIndicator->setFixedSize(QSize(32, 32)); 0139 0140 m_ProgressLayout = new QHBoxLayout(); 0141 m_ProgressLayout->setObjectName("ProgressLayout"); 0142 m_ProgressLayout->addWidget(m_ProgressLabel); 0143 m_ProgressLayout->addWidget(m_ProgressIndicator); 0144 0145 QGridLayout *gridLayout = qobject_cast<QGridLayout*>(layout()); 0146 if (gridLayout) 0147 { 0148 //gridLayout->addWidget(m_ProgressLabel.get(), 1, 2, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter); 0149 //gridLayout->addWidget(m_ProgressIndicator.get(), 1, 2, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter); 0150 gridLayout->addItem(m_ProgressLayout, 1, 2, 1, 2, Qt::AlignHCenter | Qt::AlignVCenter); 0151 } 0152 0153 m_ProgressTimer.start(); 0154 m_ProgressIndicator->setRange(0, m_Timeout); 0155 m_ProgressIndicator->setValue(static_cast<int>(m_Timeout)); 0156 } 0157 0158 void KSMessageBox::reset() 0159 { 0160 m_ProgressTimer.stop(); 0161 resetTimeout(); 0162 0163 QList<QPushButton *> allButtons = findChildren<QPushButton*>(); 0164 qDeleteAll(allButtons); 0165 0166 delete (m_ProgressIndicator); 0167 delete (m_ProgressLabel); 0168 if (m_ProgressLayout) 0169 { 0170 layout()->removeItem(m_ProgressLayout); 0171 delete (m_ProgressLayout); 0172 } 0173 0174 } 0175 0176 void KSMessageBox::questionYesNo(const QString &message, const QString &title, quint32 timeout, bool defaultToYes, 0177 const QString &yesText, const QString &noText) 0178 { 0179 reset(); 0180 0181 setIcon(QMessageBox::Question); 0182 setText(message); 0183 setWindowTitle(title); 0184 0185 QPushButton *yesButton = new QPushButton(yesText, this); 0186 QPushButton *noButton = new QPushButton(noText, this); 0187 0188 connect(yesButton, &QPushButton::clicked, this, &KSMessageBox::accepted); 0189 connect(noButton, &QPushButton::clicked, this, &KSMessageBox::rejected); 0190 0191 addButton(yesButton, QMessageBox::ActionRole); 0192 addButton(noButton, QMessageBox::ActionRole); 0193 0194 0195 setDefaultButton(defaultToYes ? yesButton : noButton); 0196 yesButton->setDefault(defaultToYes); 0197 noButton->setDefault(!defaultToYes); 0198 0199 setupTimeout(timeout); 0200 0201 open(); 0202 0203 emit newMessage(createMessageObject()); 0204 } 0205 0206 void KSMessageBox::warningContinueCancel(const QString &message, const QString &title, quint32 timeout, 0207 bool defaultToContinue, 0208 const QString &continueText, const QString &cancelText) 0209 { 0210 reset(); 0211 0212 setIcon(QMessageBox::Warning); 0213 setText(message); 0214 setWindowTitle(title); 0215 0216 QPushButton *continueButton = new QPushButton(continueText, this); 0217 QPushButton *cancelButton = new QPushButton(cancelText, this); 0218 0219 connect(continueButton, &QPushButton::clicked, this, &KSMessageBox::accepted); 0220 connect(cancelButton, &QPushButton::clicked, this, &KSMessageBox::rejected); 0221 0222 addButton(continueButton, QMessageBox::ActionRole); 0223 addButton(cancelButton, QMessageBox::ActionRole); 0224 0225 setDefaultButton(defaultToContinue ? continueButton : cancelButton); 0226 continueButton->setDefault(defaultToContinue); 0227 cancelButton->setDefault(!defaultToContinue); 0228 0229 setupTimeout(timeout); 0230 0231 open(); 0232 0233 emit newMessage(createMessageObject()); 0234 } 0235 0236 void KSMessageBox::transient(const QString &message, const QString &title) 0237 { 0238 #ifdef KSTARS_LITE 0239 Q_UNUSED(title); 0240 KStarsLite::Instance()->notificationMessage(message); 0241 #else 0242 QPointer<QMessageBox> msgBox = new QMessageBox(); 0243 msgBox->setAttribute(Qt::WA_DeleteOnClose); 0244 msgBox->setWindowTitle(title); 0245 msgBox->setText(message); 0246 msgBox->setModal(false); 0247 msgBox->setIcon(QMessageBox::Warning); 0248 msgBox->show(); 0249 #endif 0250 } 0251 0252 void KSMessageBox::addOKButton() 0253 { 0254 QPushButton *okButton = new QPushButton(i18n("Ok"), this); 0255 connect(okButton, &QPushButton::clicked, this, &KSMessageBox::accepted); 0256 addButton(okButton, QMessageBox::AcceptRole); 0257 setDefaultButton(okButton); 0258 } 0259 0260 void KSMessageBox::timerTick() 0261 { 0262 m_Timeout--; 0263 m_ProgressIndicator->setValue(static_cast<int>(m_Timeout)); 0264 0265 if (m_Timeout == 0) 0266 { 0267 m_ProgressTimer.stop(); 0268 if (defaultButton()) 0269 defaultButton()->animateClick(); 0270 else 0271 reject(); 0272 } 0273 } 0274 0275 QJsonObject KSMessageBox::createMessageObject() 0276 { 0277 QJsonObject message; 0278 QJsonArray buttons; 0279 0280 message.insert("title", windowTitle()); 0281 message.insert("message", text()); 0282 message.insert("icon", icon()); 0283 message.insert("timeout", static_cast<int32_t>(m_Timeout)); 0284 0285 for (const auto oneButton : findChildren<QPushButton*>()) 0286 { 0287 buttons.append(oneButton->text()); 0288 if (oneButton == defaultButton()) 0289 message.insert("default", oneButton->text()); 0290 } 0291 0292 message.insert("buttons", buttons); 0293 0294 return message; 0295 } 0296 0297 bool KSMessageBox::selectResponse(const QString &button) 0298 { 0299 for (const auto oneButton : findChildren<QPushButton*>()) 0300 { 0301 const QString buttonText = oneButton->text().remove("&"); 0302 0303 if (button == buttonText) 0304 { 0305 oneButton->animateClick(); 0306 return true; 0307 } 0308 } 0309 0310 return false; 0311 }