File indexing completed on 2024-04-14 14:08:56

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 }