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.
Definition: timeperiod.cpp:170
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.
Definition: timeperiod.cpp:379
TimePeriod(bool allowMinute, TQWidget *parent, const char *name=0)
Constructor.
Definition: timeperiod.cpp:53
void setSelectOnStep(bool select)
Sets whether the editor text is to be selected whenever spin buttons are clicked.
Definition: timeperiod.cpp:112
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.
Definition: timeperiod.cpp:97
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.
Definition: timeperiod.cpp:130
int minutes() const
Gets the entered time period expressed in minutes.
Definition: timeperiod.cpp:151
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.
Definition: timeperiod.cpp:121
Hours/minutes time entry widget.
Definition: timespinbox.h:46
virtual void setValue(int minutes)
Sets the value of the spin box.