File indexing completed on 2024-05-12 05:14:56

0001 /*
0002  *  reminder.cpp  -  reminder setting widget
0003  *  Program:  kalarm
0004  *  SPDX-FileCopyrightText: 2003-2022 David Jarvie <djarvie@kde.org>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "reminder.h"
0010 
0011 #include "preferences.h"
0012 #include "timeselector.h"
0013 #include "lib/checkbox.h"
0014 #include "lib/combobox.h"
0015 #include "kalarmcalendar/kadatetime.h"
0016 
0017 #include <KCalendarCore/Duration>
0018 
0019 #include <KLocalizedString>
0020 
0021 #include <QVBoxLayout>
0022 #include <QHBoxLayout>
0023 
0024 using namespace KAlarmCal;
0025 using namespace KCalendarCore;
0026 
0027 // Collect these widget labels together to ensure consistent wording and
0028 // translations across different modules.
0029 QString Reminder::i18n_chk_FirstRecurrenceOnly()   { return i18nc("@option:check", "Reminder for first recurrence only"); }
0030 
0031 #define i18n_in_advance i18nc("@item:inlistbox", "in advance")
0032 
0033 
0034 Reminder::Reminder(const QString& reminderWhatsThis, const QString& valueWhatsThis,
0035                    const QString& beforeAfterWhatsThis, bool allowHourMinute,
0036                    bool showOnceOnly, QWidget* parent)
0037     : QFrame(parent)
0038     , mOnceOnlyEnabled(showOnceOnly)
0039 {
0040     auto topLayout = new QVBoxLayout(this);
0041     topLayout->setContentsMargins(0, 0, 0, 0);
0042 
0043     mTime = new TimeSelector(i18nc("@option:check", "Reminder:"), reminderWhatsThis,
0044                              valueWhatsThis, allowHourMinute, this);
0045     mTimeSignCombo = mTime->createSignCombo();
0046     mTimeSignCombo->addItem(i18n_in_advance);
0047     mTimeSignCombo->addItem(i18nc("@item:inlistbox", "afterwards"));
0048     mTimeSignCombo->setWhatsThis(beforeAfterWhatsThis);
0049     mTimeSignCombo->setCurrentIndex(0);   // default to "in advance"
0050     connect(mTime, &TimeSelector::toggled, this, &Reminder::slotReminderToggled);
0051     connect(mTime, &TimeSelector::valueChanged, this, &Reminder::changed);
0052     connect(mTimeSignCombo, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged), this, &Reminder::changed);
0053     topLayout->addWidget(mTime, 0, Qt::AlignLeft);
0054 
0055     if (showOnceOnly)
0056     {
0057         auto layout = new QHBoxLayout();
0058         layout->setContentsMargins(0, 0, 0, 0);
0059         const int indent = CheckBox::textIndent(mTime);
0060         if (layoutDirection() == Qt::LeftToRight)
0061             layout->setContentsMargins(indent, 0, 0, 0);
0062         else
0063             layout->setContentsMargins(0, 0, indent, 0);
0064         topLayout->addLayout(layout);
0065         mOnceOnly = new CheckBox(i18n_chk_FirstRecurrenceOnly(), this);
0066         connect(mOnceOnly, &CheckBox::toggled, this, &Reminder::changed);
0067         mOnceOnly->setWhatsThis(i18nc("@info:whatsthis", "Display the reminder only for the first time the alarm is scheduled"));
0068         layout->addWidget(mOnceOnly);
0069         layout->addStretch();
0070     }
0071     else
0072         mOnceOnly = nullptr;
0073 }
0074 
0075 /******************************************************************************
0076 * Allow or disallow advance reminder selection.
0077 */
0078 void Reminder::setAfterOnly(bool afterOnly)
0079 {
0080     if (afterOnly  &&  mTimeSignCombo->count() == 2)
0081         mTimeSignCombo->removeItem(0);
0082     else if (!afterOnly  &&  mTimeSignCombo->count() == 1)
0083         mTimeSignCombo->insertItem(0, i18n_in_advance);
0084 }
0085 
0086 /******************************************************************************
0087 * Set the read-only status.
0088 */
0089 void Reminder::setReadOnly(bool ro)
0090 {
0091     if (ro != mReadOnly)
0092     {
0093         mReadOnly = ro;
0094         mTime->setReadOnly(mReadOnly);
0095         if (mOnceOnly)
0096             mOnceOnly->setReadOnly(mReadOnly);
0097     }
0098 }
0099 
0100 bool Reminder::isReminder() const
0101 {
0102     return mTime->isChecked();
0103 }
0104 
0105 bool Reminder::isOnceOnly() const
0106 {
0107     return mOnceOnly  &&  mOnceOnly->isEnabled()  &&  mOnceOnly->isChecked();
0108 }
0109 
0110 void Reminder::setOnceOnly(bool onceOnly)
0111 {
0112     if (mOnceOnly)
0113         mOnceOnly->setChecked(onceOnly);
0114 }
0115 
0116 /******************************************************************************
0117 * Specify whether the once-only checkbox is allowed to be enabled.
0118 */
0119 void Reminder::enableOnceOnly(bool enable)
0120 {
0121     if (mOnceOnly)
0122     {
0123         mOnceOnlyEnabled = enable;
0124         mOnceOnly->setEnabled(enable && mTime->isChecked());
0125     }
0126 }
0127 
0128 void Reminder::setMaximum(int hourmin, int days)
0129 {
0130     mTime->setMaximum(hourmin, days);
0131 }
0132 
0133 /******************************************************************************
0134 * Get the specified number of minutes in advance of the main alarm the
0135 * reminder is to be.
0136 * Reply > 0 if advance reminder
0137 *       < 0 if reminder after main alarm
0138 *       = 0 if no reminder.
0139 */
0140 int Reminder::minutes() const
0141 {
0142     int index = mTimeSignCombo->currentIndex();
0143     if (mTimeSignCombo->count() == 1)
0144         ++index;    // "in advance" is not available
0145     int sign = index ? -1 : 1;
0146     return mTime->period().asSeconds() * sign / 60;
0147 }
0148 
0149 /******************************************************************************
0150 * Initialise the controls with a specified reminder time.
0151 */
0152 void Reminder::setMinutes(int minutes, bool dateOnly)
0153 {
0154     bool neg = (minutes < 0);
0155     minutes = abs(minutes);
0156     Duration period;
0157     if (minutes % (24*60))
0158         period = Duration(minutes * 60, Duration::Seconds);
0159     else
0160         period = Duration(minutes / (24*60), Duration::Days);
0161     mTime->setPeriod(period, dateOnly, Preferences::defaultReminderUnits());
0162     mTimeSignCombo->setCurrentIndex(neg ? 1 : 0);
0163 }
0164 
0165 /******************************************************************************
0166 * Set the reminder units to days if "Any time" is checked.
0167 */
0168 void Reminder::setDateOnly(bool dateOnly)
0169 {
0170     mTime->setDateOnly(dateOnly);
0171 }
0172 
0173 /******************************************************************************
0174 * Set the input focus on the count field.
0175 */
0176 void Reminder::setFocusOnCount()
0177 {
0178     mTime->setFocusOnCount();
0179 }
0180 
0181 /******************************************************************************
0182 * Called when the Reminder checkbox is toggled.
0183 */
0184 void Reminder::slotReminderToggled(bool on)
0185 {
0186     if (mOnceOnly)
0187         mOnceOnly->setEnabled(on && mOnceOnlyEnabled);
0188 }
0189 
0190 /******************************************************************************
0191 * Called when the start time relating to the reminder has changed.
0192 * Sets the default reminder time units appropriately, if no reminder time is
0193 * currently set.
0194 */
0195 void Reminder::setDefaultUnits(const KADateTime& dt)
0196 {
0197     if (mTime->isChecked())
0198         return;   // don't change units if reminder is already set
0199     TimePeriod::Units units;
0200     TimePeriod::Units currentUnits = mTime->units();
0201     if (KADateTime::currentDateTime(dt.timeSpec()).daysTo(dt) < 7)
0202     {
0203         if (currentUnits == TimePeriod::Minutes  ||  currentUnits == TimePeriod::HoursMinutes)
0204             return;
0205         units = (Preferences::defaultReminderUnits() == TimePeriod::Minutes)
0206               ? TimePeriod::Minutes : TimePeriod::HoursMinutes;
0207     }
0208     else
0209     {
0210         if (currentUnits == TimePeriod::Days  ||  currentUnits == TimePeriod::Weeks)
0211             return;
0212         units = TimePeriod::Days;
0213     }
0214     mTime->setUnits(units);
0215 }
0216 
0217 #include "moc_reminder.cpp"
0218 
0219 // vim: et sw=4: