libtdepim

ktimeedit.cpp
1/*
2 This file is part of libtdepim.
3
4 Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5 Copyright (c) 1999 Ian Dawes <iadawes@globalserve.net>
6 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
22 As a special exception, permission is given to link this program
23 with any edition of TQt, and distribute the resulting executable,
24 without including the source code for TQt in the source distribution.
25*/
26
27#include <tqkeycode.h>
28#include <tqcombobox.h>
29#include <tqdatetime.h>
30#include <tqlineedit.h>
31
32#include <tdemessagebox.h>
33#include <tdeglobal.h>
34#include <kdebug.h>
35#include <tdelocale.h>
36
37#include "ktimeedit.h"
38#include <tqvalidator.h>
39#include "ktimeedit.moc"
40
41// Validator for a time value with only hours and minutes (no seconds)
42// Mostly locale aware. Author: David Faure <faure@kde.org>
43class KOTimeValidator : public TQValidator
44{
45public:
46 KOTimeValidator(TQWidget* parent, const char* name=0) : TQValidator(parent, name) {}
47
48 virtual State validate(TQString& str, int& /*cursorPos*/) const
49 {
50 int length = str.length();
51 // empty string is intermediate so one can clear the edit line and start from scratch
52 if ( length <= 0 )
53 return Intermediate;
54
55 bool ok = false;
56 /*TQTime time =*/ TDEGlobal::locale()->readTime(str, TDELocale::WithoutSeconds, &ok);
57 if ( ok )
58 return Acceptable;
59// kdDebug(5300)<<"Time "<<str<<" not directly acceptable, trying military format "<<endl;
60 // Also try to accept times in "military format", i.e. no delimiter, like 1200
61 int tm = str.toInt( &ok );
62 if ( ok && ( 0 <= tm ) ) {
63 if ( ( tm < 2400 ) && ( tm%100 < 60 ) )
64 return Acceptable;
65 else
66 return Intermediate;
67 }
68// kdDebug(5300)<<str<<" not acceptable or intermediate for military format, either "<<str<<endl;
69
70 // readTime doesn't help knowing when the string is "Intermediate".
71 // HACK. Not fully locale aware etc. (esp. the separator is '.' in sv_SE...)
72 TQChar sep = ':';
73 // I want to allow "HH:", ":MM" and ":" to make editing easier
74 if ( str[0] == sep )
75 {
76 if ( length == 1 ) // just ":"
77 return Intermediate;
78 TQString minutes = str.mid(1);
79 int m = minutes.toInt(&ok);
80 if ( ok && m >= 0 && m < 60 )
81 return Intermediate;
82 } else if ( str[str.length()-1] == sep )
83 {
84 TQString hours = str.left(length-1);
85 int h = hours.toInt(&ok);
86 if ( ok && h >= 0 && h < 24 )
87 return Intermediate;
88 }
89// return Invalid;
90 return Intermediate;
91 }
92 virtual void fixup ( TQString & input ) const {
93 bool ok = false;
94 TDEGlobal::locale()->readTime( input, TDELocale::WithoutSeconds, &ok );
95 if ( !ok ) {
96 // Also try to accept times in "military format", i.e. no delimiter, like 1200
97 int tm = input.toInt( &ok );
98 if ( ( 0 <= tm ) && ( tm < 2400 ) && ( tm%100 < 60 ) && ok ) {
99 input = TDEGlobal::locale()->formatTime( TQTime( tm / 100, tm % 100, 0 ) );
100 }
101 }
102 }
103};
104
105// KTimeWidget/TQTimeEdit provide nicer editing, but don't provide a combobox.
106// Difficult to get all in one...
107// But TQt-3.2 will offer TQLineEdit::setMask, so a "99:99" mask would help.
108KTimeEdit::KTimeEdit( TQWidget *parent, TQTime qt, const char *name )
109 : TQComboBox( true, parent, name )
110{
111 setInsertionPolicy( NoInsertion );
112 setValidator( new KOTimeValidator( this ) );
113
114 mTime = qt;
115
116// mNoTimeString = i18n("No Time");
117// insertItem( mNoTimeString );
118
119 // Fill combo box with selection of times in localized format.
120 TQTime timeEntry(0,0,0);
121 do {
122 insertItem(TDEGlobal::locale()->formatTime(timeEntry));
123 timeEntry = timeEntry.addSecs(60*15);
124 } while (!timeEntry.isNull());
125 // Add end of day.
126 insertItem( TDEGlobal::locale()->formatTime( TQTime( 23, 59, 59 ) ) );
127
128 updateText();
129 setFocusPolicy(TQWidget::StrongFocus);
130
131 connect(this, TQ_SIGNAL(activated(int)), this, TQ_SLOT(active(int)));
132 connect(this, TQ_SIGNAL(highlighted(int)), this, TQ_SLOT(hilit(int)));
133 connect(this, TQ_SIGNAL(textChanged(const TQString&)),this,TQ_SLOT(changedText()));
134}
135
136KTimeEdit::~KTimeEdit()
137{
138}
139
141{
142 // Can't happen
143 if ( currentText().isEmpty() ) return false;
144 //if ( currentText() == mNoTimeString ) return false;
145
146 return true; // always
147}
148
149TQTime KTimeEdit::getTime() const
150{
151 //kdDebug(5300) << "KTimeEdit::getTime(), currentText() = " << currentText() << endl;
152 // TODO use TDELocale::WithoutSeconds in HEAD
153 bool ok = false;
154 TQTime time = TDEGlobal::locale()->readTime( currentText(), TDELocale::WithoutSeconds, &ok );
155 if ( !ok ) {
156 // Also try to accept times in "military format", i.e. no delimiter, like 1200
157 int tm = currentText().toInt( &ok );
158 if ( ( 0 <= tm ) && ( tm < 2400 ) && ( tm%100 < 60 ) && ok ) {
159 time.setHMS( tm / 100, tm % 100, 0 );
160 } else {
161 ok = false;
162 }
163 }
164 // kdDebug(5300) << "KTimeEdit::getTime(): " << time.toString() << endl;
165 return time;
166}
167
168TQSizePolicy KTimeEdit::sizePolicy() const
169{
170 // Set size policy to Fixed, because edit cannot contain more text than the
171 // string representing the time. It doesn't make sense to provide more space.
172 TQSizePolicy sizePolicy(TQSizePolicy::Fixed,TQSizePolicy::Fixed);
173
174 return sizePolicy;
175}
176
177void KTimeEdit::setTime(TQTime newTime)
178{
179 if ( mTime != newTime )
180 {
181 kdDebug(5300) << "KTimeEdit::setTime(): " << TQString(newTime.toString()) << endl;
182
183 mTime = newTime;
184 updateText();
185 }
186}
187
188void KTimeEdit::active(int i)
189{
190 // The last entry, 23:59, is a special case
191 if( i == count() - 1 )
192 mTime = TQTime( 23, 59, 0 );
193 else
194 mTime = TQTime(0,0,0).addSecs(i*15*60);
195 emit timeChanged(mTime);
196}
197
198void KTimeEdit::hilit(int )
199{
200 // we don't currently need to do anything here.
201}
202
203void KTimeEdit::addTime(TQTime qt)
204{
205 // Calculate the new time.
206 mTime = qt.addSecs(mTime.minute()*60+mTime.hour()*3600);
207 updateText();
208 emit timeChanged(mTime);
209}
210
211void KTimeEdit::subTime(TQTime qt)
212{
213 int h, m;
214
215 // Note that we cannot use the same method for determining the new
216 // time as we did in addTime, because TQTime does not handle adding
217 // negative seconds well at all.
218 h = mTime.hour()-qt.hour();
219 m = mTime.minute()-qt.minute();
220
221 if(m < 0) {
222 m += 60;
223 h -= 1;
224 }
225
226 if(h < 0) {
227 h += 24;
228 }
229
230 // store the newly calculated time.
231 mTime.setHMS(h, m, 0);
232 updateText();
233 emit timeChanged(mTime);
234}
235
236void KTimeEdit::keyPressEvent(TQKeyEvent *qke)
237{
238 switch(qke->key()) {
239 case Key_Down:
240 addTime(TQTime(0,1,0));
241 break;
242 case Key_Up:
243 subTime(TQTime(0,1,0));
244 break;
245 case Key_Prior:
246 subTime(TQTime(1,0,0));
247 break;
248 case Key_Next:
249 addTime(TQTime(1,0,0));
250 break;
251 default:
252 TQComboBox::keyPressEvent(qke);
253 break;
254 } // switch
255}
256
257void KTimeEdit::updateText()
258{
259// kdDebug(5300) << "KTimeEdit::updateText() " << endl;
260 TQString s = TDEGlobal::locale()->formatTime(mTime);
261 // Set the text but without emitting signals, nor losing the cursor position
262 TQLineEdit *line = lineEdit();
263 line->blockSignals(true);
264 int pos = line->cursorPosition();
265
266 // select item with nearest time, must be done while line edit is blocked
267 // as setCurrentItem() calls setText() with triggers KTimeEdit::changedText()
268 setCurrentItem((mTime.hour()*4)+((mTime.minute()+7)/15));
269
270 line->setText(s);
271 line->setCursorPosition(pos);
272 line->blockSignals(false);
273
274// kdDebug(5300) << "KTimeEdit::updateText(): " << s << endl;
275}
276
278{
279 int cursorPos = lineEdit()->cursorPosition();
280 TQString str = currentText();
281 return validator()->validate( str, cursorPos ) == TQValidator::Acceptable;
282}
283
284void KTimeEdit::changedText()
285{
286 //kdDebug(5300) << "KTimeEdit::changedText()" << endl;
287 if ( inputIsValid() )
288 {
289 mTime = getTime();
290 emit timeChanged(mTime);
291 }
292}
TQSizePolicy sizePolicy() const
returns the preferred size policy of the KTimeEdit
Definition: ktimeedit.cpp:168
void timeChanged(TQTime newt)
Emitted every time the time displayed changes.
TQTime getTime() const
returns the time that is currently set in the timeLineEdit.
Definition: ktimeedit.cpp:149
KTimeEdit(TQWidget *parent=0, TQTime qt=TQTime(12, 0), const char *name=0)
constructs a new time edit.
Definition: ktimeedit.cpp:108
bool hasTime() const
Returns, if a time is selected.
Definition: ktimeedit.cpp:140
bool inputIsValid() const
return true if input is a valid time and false if not
Definition: ktimeedit.cpp:277
void setTime(TQTime qt)
used to set the time which is displayed to a specific value.
Definition: ktimeedit.cpp:177