summaryrefslogtreecommitdiffstats
path: root/kalarm/lib/timeperiod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kalarm/lib/timeperiod.cpp')
-rw-r--r--kalarm/lib/timeperiod.cpp384
1 files changed, 384 insertions, 0 deletions
diff --git a/kalarm/lib/timeperiod.cpp b/kalarm/lib/timeperiod.cpp
new file mode 100644
index 000000000..22a7c3179
--- /dev/null
+++ b/kalarm/lib/timeperiod.cpp
@@ -0,0 +1,384 @@
+/*
+ * timeperiod.h - time period data entry widget
+ * Program: kalarm
+ * Copyright © 2003,2004,2007,2008 by David Jarvie <djarvie@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kalarm.h"
+
+#include <qwidgetstack.h>
+#include <qwhatsthis.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+
+#include "combobox.h"
+#include "spinbox.h"
+#include "timespinbox.h"
+#include "timeperiod.moc"
+
+
+// Collect these widget labels together to ensure consistent wording and
+// translations across different modules.
+QString TimePeriod::i18n_minutes() { return i18n("minutes"); }
+QString TimePeriod::i18n_Minutes() { return i18n("Minutes"); }
+QString TimePeriod::i18n_hours_mins() { return i18n("hours/minutes"); }
+QString TimePeriod::i18n_Hours_Mins() { return i18n("Hours/Minutes"); }
+QString TimePeriod::i18n_days() { return i18n("days"); }
+QString TimePeriod::i18n_Days() { return i18n("Days"); }
+QString TimePeriod::i18n_weeks() { return i18n("weeks"); }
+QString TimePeriod::i18n_Weeks() { return i18n("Weeks"); }
+
+static const int maxMinutes = 1000*60-1; // absolute maximum value for hours:minutes = 999H59M
+
+/*=============================================================================
+= Class TimePeriod
+= Contains a time unit combo box, plus a time spinbox, to select a time period.
+=============================================================================*/
+
+TimePeriod::TimePeriod(bool allowHourMinute, QWidget* parent, const char* name)
+ : QHBox(parent, name),
+ mMaxDays(9999),
+ mNoHourMinute(!allowHourMinute),
+ mReadOnly(false)
+{
+ setSpacing(KDialog::spacingHint());
+
+ mSpinStack = new QWidgetStack(this);
+ mSpinBox = new SpinBox(mSpinStack);
+ mSpinBox->setLineStep(1);
+ mSpinBox->setLineShiftStep(10);
+ mSpinBox->setRange(1, mMaxDays);
+ connect(mSpinBox, SIGNAL(valueChanged(int)), SLOT(slotDaysChanged(int)));
+ mSpinStack->addWidget(mSpinBox, 0);
+
+ mTimeSpinBox = new TimeSpinBox(0, 99999, mSpinStack);
+ mTimeSpinBox->setRange(1, maxMinutes); // max 999H59M
+ connect(mTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(slotTimeChanged(int)));
+ mSpinStack->addWidget(mTimeSpinBox, 1);
+
+ mSpinStack->setFixedSize(mSpinBox->sizeHint().expandedTo(mTimeSpinBox->sizeHint()));
+ mHourMinuteRaised = mNoHourMinute;
+ showHourMin(!mNoHourMinute);
+
+ mUnitsCombo = new ComboBox(false, this);
+ if (mNoHourMinute)
+ mDateOnlyOffset = 2;
+ else
+ {
+ mDateOnlyOffset = 0;
+ mUnitsCombo->insertItem(i18n_minutes());
+ mUnitsCombo->insertItem(i18n_hours_mins());
+ }
+ mUnitsCombo->insertItem(i18n_days());
+ mUnitsCombo->insertItem(i18n_weeks());
+ mMaxUnitShown = WEEKS;
+ mUnitsCombo->setFixedSize(mUnitsCombo->sizeHint());
+ connect(mUnitsCombo, SIGNAL(activated(int)), SLOT(slotUnitsSelected(int)));
+
+ setFocusProxy(mUnitsCombo);
+ setTabOrder(mUnitsCombo, mSpinStack);
+}
+
+void TimePeriod::setReadOnly(bool ro)
+{
+ if (ro != mReadOnly)
+ {
+ mReadOnly = ro;
+ mSpinBox->setReadOnly(ro);
+ mTimeSpinBox->setReadOnly(ro);
+ mUnitsCombo->setReadOnly(ro);
+ }
+}
+
+/******************************************************************************
+* Set whether the editor text is to be selected whenever spin buttons are
+* clicked. Default is to select them.
+*/
+void TimePeriod::setSelectOnStep(bool sel)
+{
+ mSpinBox->setSelectOnStep(sel);
+ mTimeSpinBox->setSelectOnStep(sel);
+}
+
+/******************************************************************************
+* Set the input focus on the count field.
+*/
+void TimePeriod::setFocusOnCount()
+{
+ mSpinStack->setFocus();
+}
+
+/******************************************************************************
+* Set the maximum values for the hours:minutes and days/weeks spinboxes.
+* If 'hourmin' = 0, the hours:minutes maximum is left unchanged.
+*/
+void TimePeriod::setMaximum(int hourmin, int days)
+{
+ int oldmins = minutes();
+ if (hourmin > 0)
+ {
+ if (hourmin > maxMinutes)
+ hourmin = maxMinutes;
+ mTimeSpinBox->setRange(1, hourmin);
+ }
+ mMaxDays = (days >= 0) ? days : 0;
+ adjustDayWeekShown();
+ setUnitRange();
+ int mins = minutes();
+ if (mins != oldmins)
+ emit valueChanged(mins);
+}
+
+/******************************************************************************
+ * Get the specified number of minutes.
+ * Reply = 0 if error.
+ */
+int TimePeriod::minutes() const
+{
+ int factor = 0;
+ switch (mUnitsCombo->currentItem() + mDateOnlyOffset)
+ {
+ case HOURS_MINUTES:
+ return mTimeSpinBox->value();
+ case MINUTES: factor = 1; break;
+ case DAYS: factor = 24*60; break;
+ case WEEKS: factor = 7*24*60; break;
+ }
+ return mSpinBox->value() * factor;
+}
+
+/******************************************************************************
+* Initialise the controls with a specified time period.
+* The time unit combo-box is initialised to 'defaultUnits', but if 'dateOnly'
+* is true, it will never be initialised to minutes or hours/minutes.
+*/
+void TimePeriod::setMinutes(int mins, bool dateOnly, TimePeriod::Units defaultUnits)
+{
+ int oldmins = minutes();
+ if (!dateOnly && mNoHourMinute)
+ dateOnly = true;
+ int item;
+ if (mins)
+ {
+ int count = mins;
+ if (mins % (24*60))
+ item = (defaultUnits == MINUTES && count <= mSpinBox->maxValue()) ? MINUTES : HOURS_MINUTES;
+ else if (mins % (7*24*60))
+ {
+ item = DAYS;
+ count = mins / (24*60);
+ }
+ else
+ {
+ item = WEEKS;
+ count = mins / (7*24*60);
+ }
+ if (item < mDateOnlyOffset)
+ item = mDateOnlyOffset;
+ else if (item > mMaxUnitShown)
+ item = mMaxUnitShown;
+ mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
+ if (item == HOURS_MINUTES)
+ mTimeSpinBox->setValue(count);
+ else
+ mSpinBox->setValue(count);
+ item = setDateOnly(mins, dateOnly, false);
+ }
+ else
+ {
+ item = defaultUnits;
+ if (item < mDateOnlyOffset)
+ item = mDateOnlyOffset;
+ else if (item > mMaxUnitShown)
+ item = mMaxUnitShown;
+ mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
+ if (dateOnly && !mDateOnlyOffset || !dateOnly && mDateOnlyOffset)
+ item = setDateOnly(mins, dateOnly, false);
+ }
+ showHourMin(item == HOURS_MINUTES && !mNoHourMinute);
+
+ int newmins = minutes();
+ if (newmins != oldmins)
+ emit valueChanged(newmins);
+}
+
+/******************************************************************************
+* Enable/disable hours/minutes units (if hours/minutes were permitted in the
+* constructor).
+*/
+TimePeriod::Units TimePeriod::setDateOnly(int mins, bool dateOnly, bool signal)
+{
+ int oldmins = 0;
+ if (signal)
+ oldmins = minutes();
+ int index = mUnitsCombo->currentItem();
+ Units units = static_cast<Units>(index + mDateOnlyOffset);
+ if (!mNoHourMinute)
+ {
+ if (!dateOnly && mDateOnlyOffset)
+ {
+ // Change from date-only to allow hours/minutes
+ mUnitsCombo->insertItem(i18n_minutes(), 0);
+ mUnitsCombo->insertItem(i18n_hours_mins(), 1);
+ mDateOnlyOffset = 0;
+ adjustDayWeekShown();
+ mUnitsCombo->setCurrentItem(index += 2);
+ }
+ else if (dateOnly && !mDateOnlyOffset)
+ {
+ // Change from allowing hours/minutes to date-only
+ mUnitsCombo->removeItem(0);
+ mUnitsCombo->removeItem(0);
+ mDateOnlyOffset = 2;
+ if (index > 2)
+ index -= 2;
+ else
+ index = 0;
+ adjustDayWeekShown();
+ mUnitsCombo->setCurrentItem(index);
+ if (units == HOURS_MINUTES || units == MINUTES)
+ {
+ // Set units to days and round up the warning period
+ units = DAYS;
+ mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
+ mSpinBox->setValue((mins + 1439) / 1440);
+ }
+ showHourMin(false);
+ }
+ }
+
+ if (signal)
+ {
+ int newmins = minutes();
+ if (newmins != oldmins)
+ emit valueChanged(newmins);
+ }
+ return units;
+}
+
+/******************************************************************************
+* Adjust the days/weeks units shown to suit the maximum days limit.
+*/
+void TimePeriod::adjustDayWeekShown()
+{
+ Units newMaxUnitShown = (mMaxDays >= 7) ? WEEKS : (mMaxDays || mDateOnlyOffset) ? DAYS : HOURS_MINUTES;
+ if (newMaxUnitShown > mMaxUnitShown)
+ {
+ if (mMaxUnitShown < DAYS)
+ mUnitsCombo->insertItem(i18n_days());
+ if (newMaxUnitShown == WEEKS)
+ mUnitsCombo->insertItem(i18n_weeks());
+ }
+ else if (newMaxUnitShown < mMaxUnitShown)
+ {
+ if (mMaxUnitShown == WEEKS)
+ mUnitsCombo->removeItem(WEEKS - mDateOnlyOffset);
+ if (newMaxUnitShown < DAYS)
+ mUnitsCombo->removeItem(DAYS - mDateOnlyOffset);
+ }
+ mMaxUnitShown = newMaxUnitShown;
+}
+
+/******************************************************************************
+* Set the maximum value which may be entered into the day/week count field,
+* depending on the current unit selection.
+*/
+void TimePeriod::setUnitRange()
+{
+ int maxval;
+ switch (static_cast<Units>(mUnitsCombo->currentItem() + mDateOnlyOffset))
+ {
+ case WEEKS:
+ maxval = mMaxDays / 7;
+ if (maxval)
+ break;
+ mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
+ // fall through to DAYS
+ case DAYS:
+ maxval = mMaxDays ? mMaxDays : 1;
+ break;
+ case MINUTES:
+ maxval = mTimeSpinBox->maxValue();
+ break;
+ case HOURS_MINUTES:
+ default:
+ return;
+ }
+ mSpinBox->setRange(1, maxval);
+}
+
+/******************************************************************************
+* Called when a new item is made current in the time units combo box.
+*/
+void TimePeriod::slotUnitsSelected(int index)
+{
+ setUnitRange();
+ showHourMin(index + mDateOnlyOffset == HOURS_MINUTES);
+ emit valueChanged(minutes());
+}
+
+/******************************************************************************
+* Called when the value of the days/weeks spin box changes.
+*/
+void TimePeriod::slotDaysChanged(int)
+{
+ if (!mHourMinuteRaised)
+ emit valueChanged(minutes());
+}
+
+/******************************************************************************
+* Called when the value of the time spin box changes.
+*/
+void TimePeriod::slotTimeChanged(int value)
+{
+ if (mHourMinuteRaised)
+ emit valueChanged(value);
+}
+
+/******************************************************************************
+ * Set the currently displayed count widget.
+ */
+void TimePeriod::showHourMin(bool hourMinute)
+{
+ if (hourMinute != mHourMinuteRaised)
+ {
+ mHourMinuteRaised = hourMinute;
+ if (hourMinute)
+ {
+ mSpinStack->raiseWidget(mTimeSpinBox);
+ mSpinStack->setFocusProxy(mTimeSpinBox);
+ }
+ else
+ {
+ mSpinStack->raiseWidget(mSpinBox);
+ mSpinStack->setFocusProxy(mSpinBox);
+ }
+ }
+}
+
+/******************************************************************************
+ * Set separate WhatsThis texts for the count spinboxes and the units combobox.
+ * If the hours:minutes text is omitted, both spinboxes are set to the same
+ * WhatsThis text.
+ */
+void TimePeriod::setWhatsThis(const QString& units, const QString& dayWeek, const QString& hourMin)
+{
+ QWhatsThis::add(mUnitsCombo, units);
+ QWhatsThis::add(mSpinBox, dayWeek);
+ QWhatsThis::add(mTimeSpinBox, (hourMin.isNull() ? dayWeek : hourMin));
+}