File indexing completed on 2024-05-12 05:15:03

0001 /*
0002   This file is part of the kcal library.
0003 
0004   SPDX-FileCopyrightText: Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0005   SPDX-FileContributor: Kevin Krammer <krake@kdab.com>
0006 
0007   SPDX-FileCopyrightText: 2015 SĂ©rgio Martins <iamsergio@gmail.com>
0008 
0009   SPDX-License-Identifier: LGPL-2.0-or-later
0010 */
0011 
0012 #include "recurrenceactions.h"
0013 
0014 #include "ui_recurrenceactionsscopewidget.h"
0015 
0016 #include <KGuiItem>
0017 #include <KLocalizedString>
0018 #include <KMessageBox>
0019 
0020 #include <QDialog>
0021 #include <QDialogButtonBox>
0022 #include <QPointer>
0023 #include <QPushButton>
0024 #include <QStyle>
0025 #include <QStyleOption>
0026 #include <QVBoxLayout>
0027 
0028 using namespace KCalUtils;
0029 using namespace KCalUtils::RecurrenceActions;
0030 using namespace KCalendarCore;
0031 
0032 class ScopeWidget : public QWidget
0033 {
0034     Q_OBJECT
0035 public:
0036     ScopeWidget(int availableChoices, const QDateTime &dateTime, QWidget *parent)
0037         : QWidget(parent)
0038         , mAvailableChoices(availableChoices)
0039     {
0040         mUi.setupUi(this);
0041 
0042         if ((mAvailableChoices & PastOccurrences) == 0) {
0043             mUi.checkBoxPast->hide();
0044         } else {
0045             mUi.checkBoxPast->setText(
0046                 i18nc("@option:check calendar items before a certain date", "Items before %1", QLocale().toString(dateTime, QLocale::ShortFormat)));
0047         }
0048         if ((mAvailableChoices & SelectedOccurrence) == 0) {
0049             mUi.checkBoxSelected->hide();
0050         } else {
0051             mUi.checkBoxSelected->setText(i18nc("@option:check currently selected calendar item", "Selected item"));
0052         }
0053         if ((mAvailableChoices & FutureOccurrences) == 0) {
0054             mUi.checkBoxFuture->hide();
0055         } else {
0056             mUi.checkBoxFuture->setText(
0057                 i18nc("@option:check calendar items after a certain date", "Items after %1", QLocale().toString(dateTime, QLocale::ShortFormat)));
0058         }
0059     }
0060 
0061     ~ScopeWidget() override;
0062 
0063     void setMessage(const QString &message);
0064     void setIcon(const QIcon &icon);
0065 
0066     void setCheckedChoices(int choices);
0067     [[nodiscard]] int checkedChoices() const;
0068 
0069 private:
0070     const int mAvailableChoices;
0071     Ui_RecurrenceActionsScopeWidget mUi;
0072 };
0073 
0074 ScopeWidget::~ScopeWidget()
0075 {
0076 }
0077 
0078 void ScopeWidget::setMessage(const QString &message)
0079 {
0080     mUi.messageLabel->setText(message);
0081 }
0082 
0083 void ScopeWidget::setIcon(const QIcon &icon)
0084 {
0085     QStyleOption option;
0086     option.initFrom(this);
0087     mUi.iconLabel->setPixmap(icon.pixmap(style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, this)));
0088 }
0089 
0090 void ScopeWidget::setCheckedChoices(int choices)
0091 {
0092     // mask with available ones
0093     choices &= mAvailableChoices;
0094 
0095     mUi.checkBoxPast->setChecked((choices & PastOccurrences) != 0);
0096     mUi.checkBoxSelected->setChecked((choices & SelectedOccurrence) != 0);
0097     mUi.checkBoxFuture->setChecked((choices & FutureOccurrences) != 0);
0098 }
0099 
0100 int ScopeWidget::checkedChoices() const
0101 {
0102     int result = NoOccurrence;
0103 
0104     if (mUi.checkBoxPast->isChecked()) {
0105         result |= PastOccurrences;
0106     }
0107     if (mUi.checkBoxSelected->isChecked()) {
0108         result |= SelectedOccurrence;
0109     }
0110     if (mUi.checkBoxFuture->isChecked()) {
0111         result |= FutureOccurrences;
0112     }
0113 
0114     return result;
0115 }
0116 
0117 int RecurrenceActions::availableOccurrences(const Incidence::Ptr &incidence, const QDateTime &selectedOccurrence)
0118 {
0119     int result = NoOccurrence;
0120 
0121     if (incidence->recurrence()->recursOn(selectedOccurrence.date(), selectedOccurrence.timeZone())) {
0122         result |= SelectedOccurrence;
0123     }
0124 
0125     if (incidence->recurrence()->getPreviousDateTime(selectedOccurrence).isValid()) {
0126         result |= PastOccurrences;
0127     }
0128 
0129     if (incidence->recurrence()->getNextDateTime(selectedOccurrence).isValid()) {
0130         result |= FutureOccurrences;
0131     }
0132 
0133     return result;
0134 }
0135 
0136 static QDialog *
0137 createDialog(QDialogButtonBox::StandardButtons buttons, const QString &caption, QWidget *mainWidget, QDialogButtonBox **buttonBox, QWidget *parent)
0138 {
0139     QPointer<QDialog> dialog = new QDialog(parent);
0140     dialog->setWindowTitle(caption);
0141     auto mainLayout = new QVBoxLayout();
0142     dialog->setLayout(mainLayout);
0143 
0144     *buttonBox = new QDialogButtonBox(buttons, parent);
0145     QPushButton *okButton = (*buttonBox)->button(QDialogButtonBox::Ok);
0146     okButton->setDefault(true);
0147     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0148     QObject::connect(*buttonBox, &QDialogButtonBox::accepted, dialog.data(), &QDialog::accept);
0149     QObject::connect(*buttonBox, &QDialogButtonBox::rejected, dialog.data(), &QDialog::reject);
0150     (*buttonBox)->button(QDialogButtonBox::Ok)->setDefault(true);
0151 
0152     if (mainWidget) {
0153         mainLayout->addWidget(mainWidget);
0154     }
0155 
0156     mainLayout->addWidget(*buttonBox);
0157 
0158     return dialog;
0159 }
0160 
0161 int RecurrenceActions::questionMultipleChoice(const QDateTime &selectedOccurrence,
0162                                               const QString &message,
0163                                               const QString &caption,
0164                                               const KGuiItem &action,
0165                                               int availableChoices,
0166                                               int preselectedChoices,
0167                                               QWidget *parent)
0168 {
0169     QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
0170     auto widget = new ScopeWidget(availableChoices, selectedOccurrence, nullptr);
0171     QDialogButtonBox *buttonBox = nullptr;
0172     auto dialog = createDialog(buttons, caption, widget, &buttonBox, parent);
0173 
0174     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), action);
0175 
0176     widget->setMessage(message);
0177     widget->setIcon(widget->style()->standardIcon(QStyle::SP_MessageBoxQuestion));
0178     widget->setCheckedChoices(preselectedChoices);
0179 
0180     const int result = dialog->exec();
0181     if (dialog) {
0182         dialog->deleteLater();
0183     }
0184 
0185     if (result == QDialog::Rejected) {
0186         return NoOccurrence;
0187     }
0188 
0189     return widget->checkedChoices();
0190 }
0191 
0192 int RecurrenceActions::questionSelectedAllCancel(const QString &message,
0193                                                  const QString &caption,
0194                                                  const KGuiItem &actionSelected,
0195                                                  const KGuiItem &actionAll,
0196                                                  QWidget *parent)
0197 {
0198     QPointer<QDialog> dialog = new QDialog(parent);
0199     dialog->setWindowTitle(caption);
0200     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::No | QDialogButtonBox::Yes, parent);
0201     dialog->setObjectName(QLatin1StringView("RecurrenceActions::questionSelectedAllCancel"));
0202 
0203     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), actionSelected);
0204     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), actionAll);
0205 
0206     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0207     okButton->setDefault(true);
0208     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0209     buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
0210 
0211     bool checkboxResult = false;
0212     int result =
0213         KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Question, message, QStringList(), QString(), &checkboxResult, KMessageBox::Notify);
0214 
0215     switch (result) {
0216     case QDialogButtonBox::Yes:
0217         return SelectedOccurrence;
0218     case QDialogButtonBox::Ok:
0219         return AllOccurrences;
0220     default:
0221         return NoOccurrence;
0222     }
0223 }
0224 
0225 int RecurrenceActions::questionSelectedFutureAllCancel(const QString &message,
0226                                                        const QString &caption,
0227                                                        const KGuiItem &actionSelected,
0228                                                        const KGuiItem &actionFuture,
0229                                                        const KGuiItem &actionAll,
0230                                                        QWidget *parent)
0231 {
0232     QPointer<QDialog> dialog = new QDialog(parent);
0233     dialog->setWindowTitle(caption);
0234 
0235     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::No | QDialogButtonBox::Yes, parent);
0236     dialog->setObjectName(QLatin1StringView("RecurrenceActions::questionSelectedFutureAllCancel"));
0237     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), actionSelected);
0238     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), actionFuture);
0239     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), actionAll);
0240     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0241     okButton->setDefault(true);
0242     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0243     buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
0244 
0245     bool checkboxResult = false;
0246     QDialogButtonBox::StandardButton result =
0247         KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Question, message, QStringList(), QString(), &checkboxResult, KMessageBox::Notify);
0248 
0249     switch (result) {
0250     case QDialogButtonBox::Yes:
0251         return SelectedOccurrence;
0252     case QDialogButtonBox::No:
0253         return FutureOccurrences;
0254     case QDialogButtonBox::Ok:
0255         return AllOccurrences;
0256     default:
0257         return NoOccurrence;
0258     }
0259 
0260     return NoOccurrence;
0261 }
0262 
0263 #include "recurrenceactions.moc"