kalarm/lib

timeperiod.cpp
1/*
2 * timeperiod.h - time period data entry widget
3 * Program: kalarm
4 * Copyright © 2003,2004,2007,2008 by David Jarvie <djarvie@kde.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include "kalarm.h"
22
23#include <tqwidgetstack.h>
24#include <tqwhatsthis.h>
25
26#include <tdelocale.h>
27#include <kdialog.h>
28
29#include "combobox.h"
30#include "spinbox.h"
31#include "timespinbox.h"
32#include "timeperiod.moc"
33
34
35// Collect these widget labels together to ensure consistent wording and
36// translations across different modules.
37TQString TimePeriod::i18n_minutes() { return i18n("minutes"); }
38TQString TimePeriod::i18n_Minutes() { return i18n("Minutes"); }
39TQString TimePeriod::i18n_hours_mins() { return i18n("hours/minutes"); }
40TQString TimePeriod::i18n_Hours_Mins() { return i18n("Hours/Minutes"); }
41TQString TimePeriod::i18n_days() { return i18n("days"); }
42TQString TimePeriod::i18n_Days() { return i18n("Days"); }
43TQString TimePeriod::i18n_weeks() { return i18n("weeks"); }
44TQString TimePeriod::i18n_Weeks() { return i18n("Weeks"); }
45
46static const int maxMinutes = 1000*60-1; // absolute maximum value for hours:minutes = 999H59M
47
48/*=============================================================================
49= Class TimePeriod
50= Contains a time unit combo box, plus a time spinbox, to select a time period.
51=============================================================================*/
52
53TimePeriod::TimePeriod(bool allowHourMinute, TQWidget* parent, const char* name)
54 : TQHBox(parent, name),
55 mMaxDays(9999),
56 mNoHourMinute(!allowHourMinute),
57 mReadOnly(false)
58{
59 setSpacing(KDialog::spacingHint());
60
61 mSpinStack = new TQWidgetStack(this);
62 mSpinBox = new SpinBox(mSpinStack);
63 mSpinBox->setLineStep(1);
64 mSpinBox->setLineShiftStep(10);
65 mSpinBox->setRange(1, mMaxDays);
66 connect(mSpinBox, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(slotDaysChanged(int)));
67 mSpinStack->addWidget(mSpinBox, 0);
68
69 mTimeSpinBox = new TimeSpinBox(0, 99999, mSpinStack);
70 mTimeSpinBox->setRange(1, maxMinutes); // max 999H59M
71 connect(mTimeSpinBox, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(slotTimeChanged(int)));
72 mSpinStack->addWidget(mTimeSpinBox, 1);
73
74 mSpinStack->setFixedSize(mSpinBox->sizeHint().expandedTo(mTimeSpinBox->sizeHint()));
75 mHourMinuteRaised = mNoHourMinute;
76 showHourMin(!mNoHourMinute);
77
78 mUnitsCombo = new ComboBox(false, this);
79 if (mNoHourMinute)
80 mDateOnlyOffset = 2;
81 else
82 {
83 mDateOnlyOffset = 0;
84 mUnitsCombo->insertItem(i18n_minutes());
85 mUnitsCombo->insertItem(i18n_hours_mins());
86 }
87 mUnitsCombo->insertItem(i18n_days());
88 mUnitsCombo->insertItem(i18n_weeks());
89 mMaxUnitShown = WEEKS;
90 mUnitsCombo->setFixedSize(mUnitsCombo->sizeHint());
91 connect(mUnitsCombo, TQ_SIGNAL(activated(int)), TQ_SLOT(slotUnitsSelected(int)));
92
93 setFocusProxy(mUnitsCombo);
94 setTabOrder(mUnitsCombo, mSpinStack);
95}
96
98{
99 if (ro != mReadOnly)
100 {
101 mReadOnly = ro;
102 mSpinBox->setReadOnly(ro);
103 mTimeSpinBox->setReadOnly(ro);
104 mUnitsCombo->setReadOnly(ro);
105 }
106}
107
108/******************************************************************************
109* Set whether the editor text is to be selected whenever spin buttons are
110* clicked. Default is to select them.
111*/
113{
114 mSpinBox->setSelectOnStep(sel);
115 mTimeSpinBox->setSelectOnStep(sel);
116}
117
118/******************************************************************************
119* Set the input focus on the count field.
120*/
122{
123 mSpinStack->setFocus();
124}
125
126/******************************************************************************
127* Set the maximum values for the hours:minutes and days/weeks spinboxes.
128* If 'hourmin' = 0, the hours:minutes maximum is left unchanged.
129*/
130void TimePeriod::setMaximum(int hourmin, int days)
131{
132 int oldmins = minutes();
133 if (hourmin > 0)
134 {
135 if (hourmin > maxMinutes)
136 hourmin = maxMinutes;
137 mTimeSpinBox->setRange(1, hourmin);
138 }
139 mMaxDays = (days >= 0) ? days : 0;
140 adjustDayWeekShown();
141 setUnitRange();
142 int mins = minutes();
143 if (mins != oldmins)
144 emit valueChanged(mins);
145}
146
147/******************************************************************************
148 * Get the specified number of minutes.
149 * Reply = 0 if error.
150 */
152{
153 int factor = 0;
154 switch (mUnitsCombo->currentItem() + mDateOnlyOffset)
155 {
156 case HOURS_MINUTES:
157 return mTimeSpinBox->value();
158 case MINUTES: factor = 1; break;
159 case DAYS: factor = 24*60; break;
160 case WEEKS: factor = 7*24*60; break;
161 }
162 return mSpinBox->value() * factor;
163}
164
165/******************************************************************************
166* Initialise the controls with a specified time period.
167* The time unit combo-box is initialised to 'defaultUnits', but if 'dateOnly'
168* is true, it will never be initialised to minutes or hours/minutes.
169*/
170void TimePeriod::setMinutes(int mins, bool dateOnly, TimePeriod::Units defaultUnits)
171{
172 int oldmins = minutes();
173 if (!dateOnly && mNoHourMinute)
174 dateOnly = true;
175 int item;
176 if (mins)
177 {
178 int count = mins;
179 if (mins % (24*60))
180 item = (defaultUnits == MINUTES && count <= mSpinBox->maxValue()) ? MINUTES : HOURS_MINUTES;
181 else if (mins % (7*24*60))
182 {
183 item = DAYS;
184 count = mins / (24*60);
185 }
186 else
187 {
188 item = WEEKS;
189 count = mins / (7*24*60);
190 }
191 if (item < mDateOnlyOffset)
192 item = mDateOnlyOffset;
193 else if (item > mMaxUnitShown)
194 item = mMaxUnitShown;
195 mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
196 if (item == HOURS_MINUTES)
197 mTimeSpinBox->setValue(count);
198 else
199 mSpinBox->setValue(count);
200 item = setDateOnly(mins, dateOnly, false);
201 }
202 else
203 {
204 item = defaultUnits;
205 if (item < mDateOnlyOffset)
206 item = mDateOnlyOffset;
207 else if (item > mMaxUnitShown)
208 item = mMaxUnitShown;
209 mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
210 if ((dateOnly && !mDateOnlyOffset) || (!dateOnly && mDateOnlyOffset))
211 item = setDateOnly(mins, dateOnly, false);
212 }
213 showHourMin(item == HOURS_MINUTES && !mNoHourMinute);
214
215 int newmins = minutes();
216 if (newmins != oldmins)
217 emit valueChanged(newmins);
218}
219
220/******************************************************************************
221* Enable/disable hours/minutes units (if hours/minutes were permitted in the
222* constructor).
223*/
224TimePeriod::Units TimePeriod::setDateOnly(int mins, bool dateOnly, bool signal)
225{
226 int oldmins = 0;
227 if (signal)
228 oldmins = minutes();
229 int index = mUnitsCombo->currentItem();
230 Units units = static_cast<Units>(index + mDateOnlyOffset);
231 if (!mNoHourMinute)
232 {
233 if (!dateOnly && mDateOnlyOffset)
234 {
235 // Change from date-only to allow hours/minutes
236 mUnitsCombo->insertItem(i18n_minutes(), 0);
237 mUnitsCombo->insertItem(i18n_hours_mins(), 1);
238 mDateOnlyOffset = 0;
239 adjustDayWeekShown();
240 mUnitsCombo->setCurrentItem(index += 2);
241 }
242 else if (dateOnly && !mDateOnlyOffset)
243 {
244 // Change from allowing hours/minutes to date-only
245 mUnitsCombo->removeItem(0);
246 mUnitsCombo->removeItem(0);
247 mDateOnlyOffset = 2;
248 if (index > 2)
249 index -= 2;
250 else
251 index = 0;
252 adjustDayWeekShown();
253 mUnitsCombo->setCurrentItem(index);
254 if (units == HOURS_MINUTES || units == MINUTES)
255 {
256 // Set units to days and round up the warning period
257 units = DAYS;
258 mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
259 mSpinBox->setValue((mins + 1439) / 1440);
260 }
261 showHourMin(false);
262 }
263 }
264
265 if (signal)
266 {
267 int newmins = minutes();
268 if (newmins != oldmins)
269 emit valueChanged(newmins);
270 }
271 return units;
272}
273
274/******************************************************************************
275* Adjust the days/weeks units shown to suit the maximum days limit.
276*/
277void TimePeriod::adjustDayWeekShown()
278{
279 Units newMaxUnitShown = (mMaxDays >= 7) ? WEEKS : (mMaxDays || mDateOnlyOffset) ? DAYS : HOURS_MINUTES;
280 if (newMaxUnitShown > mMaxUnitShown)
281 {
282 if (mMaxUnitShown < DAYS)
283 mUnitsCombo->insertItem(i18n_days());
284 if (newMaxUnitShown == WEEKS)
285 mUnitsCombo->insertItem(i18n_weeks());
286 }
287 else if (newMaxUnitShown < mMaxUnitShown)
288 {
289 if (mMaxUnitShown == WEEKS)
290 mUnitsCombo->removeItem(WEEKS - mDateOnlyOffset);
291 if (newMaxUnitShown < DAYS)
292 mUnitsCombo->removeItem(DAYS - mDateOnlyOffset);
293 }
294 mMaxUnitShown = newMaxUnitShown;
295}
296
297/******************************************************************************
298* Set the maximum value which may be entered into the day/week count field,
299* depending on the current unit selection.
300*/
301void TimePeriod::setUnitRange()
302{
303 int maxval;
304 switch (static_cast<Units>(mUnitsCombo->currentItem() + mDateOnlyOffset))
305 {
306 case WEEKS:
307 maxval = mMaxDays / 7;
308 if (maxval)
309 break;
310 mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
311 // fall through to DAYS
312 case DAYS:
313 maxval = mMaxDays ? mMaxDays : 1;
314 break;
315 case MINUTES:
316 maxval = mTimeSpinBox->maxValue();
317 break;
318 case HOURS_MINUTES:
319 default:
320 return;
321 }
322 mSpinBox->setRange(1, maxval);
323}
324
325/******************************************************************************
326* Called when a new item is made current in the time units combo box.
327*/
328void TimePeriod::slotUnitsSelected(int index)
329{
330 setUnitRange();
331 showHourMin(index + mDateOnlyOffset == HOURS_MINUTES);
332 emit valueChanged(minutes());
333}
334
335/******************************************************************************
336* Called when the value of the days/weeks spin box changes.
337*/
338void TimePeriod::slotDaysChanged(int)
339{
340 if (!mHourMinuteRaised)
341 emit valueChanged(minutes());
342}
343
344/******************************************************************************
345* Called when the value of the time spin box changes.
346*/
347void TimePeriod::slotTimeChanged(int value)
348{
349 if (mHourMinuteRaised)
350 emit valueChanged(value);
351}
352
353/******************************************************************************
354 * Set the currently displayed count widget.
355 */
356void TimePeriod::showHourMin(bool hourMinute)
357{
358 if (hourMinute != mHourMinuteRaised)
359 {
360 mHourMinuteRaised = hourMinute;
361 if (hourMinute)
362 {
363 mSpinStack->raiseWidget(mTimeSpinBox);
364 mSpinStack->setFocusProxy(mTimeSpinBox);
365 }
366 else
367 {
368 mSpinStack->raiseWidget(mSpinBox);
369 mSpinStack->setFocusProxy(mSpinBox);
370 }
371 }
372}
373
374/******************************************************************************
375 * Set separate WhatsThis texts for the count spinboxes and the units combobox.
376 * If the hours:minutes text is omitted, both spinboxes are set to the same
377 * WhatsThis text.
378 */
379void TimePeriod::setWhatsThis(const TQString& units, const TQString& dayWeek, const TQString& hourMin)
380{
381 TQWhatsThis::add(mUnitsCombo, units);
382 TQWhatsThis::add(mSpinBox, dayWeek);
383 TQWhatsThis::add(mTimeSpinBox, (hourMin.isNull() ? dayWeek : hourMin));
384}
A TQComboBox with read-only option.
Definition combobox.h:38
virtual void setReadOnly(bool readOnly)
Sets whether the combo box is read-only for the user.
Definition combobox.cpp:35
void setRange(int minValue, int maxValue)
Sets the minimum and maximum values of the spin box.
Definition spinbox2.h:146
void setSelectOnStep(bool sel)
Sets whether the spin box value text should be selected when its value is stepped.
Definition spinbox2.h:83
int maxValue() const
Returns the maximum value of the spin box.
Definition spinbox2.h:140
virtual void setReadOnly(bool readOnly)
Sets whether the spin box can be changed by the user.
Definition spinbox2.cpp:99
int value() const
Returns the current value of the spin box.
Definition spinbox2.h:148
Spin box with accelerated shift key stepping and read-only option.
Definition spinbox.h:43
void setLineShiftStep(int step)
Sets the shifted step increment, i.e.
Definition spinbox.cpp:109
int maxValue() const
Returns the maximum value of the spin box.
Definition spinbox.h:75
void setSelectOnStep(bool sel)
Sets whether the spin box value text should be selected when its value is stepped.
Definition spinbox.h:69
virtual void setReadOnly(bool readOnly)
Sets whether the spin box can be changed by the user.
Definition spinbox.cpp:72
void setRange(int minValue, int maxValue)
Sets the minimum and maximum values of the spin box.
Definition spinbox.h:81
void setLineStep(int step)
Sets the unshifted step increment, i.e.
Definition spinbox.cpp:102
void setMinutes(int minutes, bool dateOnly, Units defaultUnits)
Initialises the time period value.
void setWhatsThis(const TQString &units, const TQString &dayWeek, const TQString &hourMin=TQString())
Sets separate WhatsThis texts for the count spin boxes and the units combo box.
TimePeriod(bool allowMinute, TQWidget *parent, const char *name=0)
Constructor.
void setSelectOnStep(bool select)
Sets whether the editor text is to be selected whenever spin buttons are clicked.
void valueChanged(int minutes)
This signal is emitted whenever the value held in the widget changes.
virtual void setReadOnly(bool readOnly)
Sets whether the widget is read-only for the user.
Units
Units for the time period.
Definition timeperiod.h:61
void setMaximum(int hourmin, int days)
Sets the maximum values for the minutes and hours/minutes, and days/weeks spin boxes.
int minutes() const
Gets the entered time period expressed in minutes.
void setDateOnly(bool dateOnly)
Enables or disables minutes and hours/minutes units in the combo box.
Definition timeperiod.h:92
void setFocusOnCount()
Sets the input focus to the count field.
Hours/minutes time entry widget.
Definition timespinbox.h:46
virtual void setValue(int minutes)
Sets the value of the spin box.