summaryrefslogtreecommitdiffabout
path: root/korganizer/ktimeedit.cpp
Unidiff
Diffstat (limited to 'korganizer/ktimeedit.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/ktimeedit.cpp528
1 files changed, 528 insertions, 0 deletions
diff --git a/korganizer/ktimeedit.cpp b/korganizer/ktimeedit.cpp
new file mode 100644
index 0000000..f9720f6
--- a/dev/null
+++ b/korganizer/ktimeedit.cpp
@@ -0,0 +1,528 @@
1/*
2 This file is part of KOrganizer.
3 Copyright (c) 1999 Preston Brown, Ian Dawes
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qkeycode.h>
25#include <qcombobox.h>
26#include <qdatetime.h>
27#include <qlineedit.h>
28#include <qapplication.h>
29
30#include <kmessagebox.h>
31#include <kglobal.h>
32#include <kdebug.h>
33#include <klocale.h>
34
35#include "ktimeedit.h"
36#include "koprefs.h"
37#include <qvalidator.h>
38#include "ktimeedit.moc"
39
40// Validator for a time value with only hours and minutes (no seconds)
41// Mostly locale aware. Author: David Faure <faure@kde.org>
42class KOTimeValidator : public QValidator
43{
44public:
45 KOTimeValidator(QWidget* parent, const char* name=0) : QValidator(parent, name) {}
46
47 virtual State validate(QString& str, int& /*cursorPos*/) const
48 {
49 return Acceptable;
50 bool ok = false;
51 // TODO use KLocale::WithoutSeconds in HEAD
52 /*QTime time =*/ KGlobal::locale()->readTime(str, &ok);
53 if ( ok )
54 return Acceptable;
55 // readTime doesn't help knowing when the string is "Intermediate".
56 int length = str.length();
57 if ( !str ) // empty string?
58 return Invalid; // there should always be a ':' in it, right?
59 // HACK. Not fully locale aware etc. (esp. the separator is '.' in sv_SE...)
60 QChar sep = ':';
61 // I want to allow "HH:", ":MM" and ":" to make editing easier
62 if ( str[0] == sep )
63 {
64 if ( length == 1 ) // just ":"
65 return Intermediate;
66 QString minutes = str.mid(1);
67 int m = minutes.toInt(&ok);
68 if ( ok && m >= 0 && m < 60 )
69 return Intermediate;
70 } else if ( str.at(str.length()-1) == sep )
71 {
72 QString hours = str.left(length-1);
73 int h = hours.toInt(&ok);
74 if ( ok && h >= 0 && h < 24 )
75 return Intermediate;
76 }
77 return Invalid;
78 }
79};
80
81// KTimeWidget/QTimeEdit provide nicer editing, but don't provide a combobox.
82// Difficult to get all in one...
83// But Qt-3.2 will offer QLineEdit::setMask, so a "99:99" mask would help.
84KOTimeEdit::KOTimeEdit(QWidget *parent, QTime qt, const char *name)
85 : QComboBox(TRUE, parent, name)
86{
87 setInsertionPolicy(NoInsertion);
88 setValidator( new KOTimeValidator( this ) );
89 mFlagKeyPressed = false;
90
91 if ( QApplication::desktop()->width() < 650 )
92 setSizeLimit ( 6 );
93 mTime = qt;
94
95// mNoTimeString = i18n("No Time");
96// insertItem( mNoTimeString );
97
98 // Fill combo box with selection of times in localized format.
99 QTime timeEntry(0,0,0);
100 do {
101 insertItem(KGlobal::locale()->formatTime(timeEntry));
102 timeEntry = timeEntry.addSecs(60*15);
103 } while (!timeEntry.isNull());
104 // Add end of day.
105 insertItem( KGlobal::locale()->formatTime( QTime( 23, 59, 59 ) ) );
106
107 updateText();
108 setFocusPolicy(QWidget::StrongFocus);
109
110 connect(this, SIGNAL(activated(int)), this, SLOT(activ(int)));
111 connect(this, SIGNAL(highlighted(int)), this, SLOT(hilit(int)));
112 connect(this,SIGNAL(textChanged(const QString&)),this,SLOT(changedText()));
113 QFontMetrics fm ( font() );
114 QString timeString = "24:00";
115 if ( KOPrefs::instance()->mPreferredTime == 1 )
116 timeString = "02:00pm";
117 int addSpace = 32;
118 if ( QApplication::desktop()->width() > 320 )
119 timeString += ":00";
120 setFixedWidth(fm.width( timeString ) + 32 );
121
122 // Highlight Background and Textcolor change from default
123 QPalette palette = QWidget::palette();
124 unsigned char red, green, blue;
125 red = palette.color( QPalette::Normal , QColorGroup::Background ).red() - 10;
126 green = palette.color( QPalette::Normal , QColorGroup::Background ).green() - 10;
127 blue = palette.color( QPalette::Normal , QColorGroup::Background ).blue() - 10;
128 palette.setColor( QColorGroup::Highlight, QColor(red,green,blue) );
129 palette.setColor( QColorGroup::HighlightedText, palette.color( QPalette::Normal , QColorGroup::Foreground ) );
130 setPalette( palette );
131}
132
133KOTimeEdit::~KOTimeEdit()
134{
135}
136
137bool KOTimeEdit::hasTime() const
138{
139 // Can't happen
140 if ( currentText().isEmpty() ) return false;
141 //if ( currentText() == mNoTimeString ) return false;
142
143 return true; // always
144}
145
146QTime KOTimeEdit::getTime() const
147{
148 //kdDebug(5850) << "KOTimeEdit::getTime(), currentText() = " << currentText() << endl;
149 // TODO use KLocale::WithoutSeconds in HEAD
150 QTime time = KGlobal::locale()->readTime(currentText());
151 // kdDebug(5850) << "KOTimeEdit::getTime(): " << time.toString() << endl;
152 return time;
153}
154/*
155QSizePolicy KOTimeEdit::sizePolicy() const
156{
157 // Set size policy to Fixed, because edit cannot contain more text than the
158 // string representing the time. It doesn't make sense to provide more space.
159 QSizePolicy sizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
160
161 return sizePolicy;
162}
163*/
164void KOTimeEdit::setTime(QTime newTime)
165{
166 if ( mTime != newTime )
167 {
168 kdDebug(5850) << "KOTimeEdit::setTime(): " << newTime.toString() << endl;
169
170 mTime = newTime;
171 updateText();
172 }
173
174}
175
176void KOTimeEdit::activ(int i)
177{
178 // The last entry, 23:59, is a special case
179 if( i == count() - 1 )
180 mTime = QTime( 23, 59, 0 );
181 else
182 mTime = QTime(0,0,0).addSecs(i*15*60);
183 emit timeChanged(mTime);
184}
185
186void KOTimeEdit::hilit(int )
187{
188 // we don't currently need to do anything here.
189}
190
191void KOTimeEdit::addTime(QTime qt, bool update)
192{
193 // Calculate the new time.
194 //qDebug("add h %d min %d ", qt.hour(),qt.minute() );
195 mTime = mTime.addSecs(qt.minute()*60+qt.hour()*3600);
196 // if ( update )
197 updateText();
198 emit timeChanged(mTime);
199}
200
201void KOTimeEdit::subTime(QTime qt, bool update)
202{
203 int h, m;
204 //qDebug("sub h %d min %d ", qt.hour(),qt.minute() );
205
206 mTime = mTime.addSecs(-(qt.minute()*60+qt.hour()*3600));
207 // store the newly calculated time.
208 // mTime.setHMS(h, m, 0);
209 //if ( update )
210 updateText();
211 emit timeChanged(mTime);
212}
213
214// void KOTimeEdit::mouseReleaseEvent ( QMouseEvent * )
215// {
216// qDebug("mouseReleaseEvent ( QMouseEvent * ) ");
217// }
218
219// void KOTimeEdit::focusInEvent ( QFocusEvent * )
220// {
221// qDebug("focusInEvent ( QFocusEvent * ) ");
222// }
223
224void KOTimeEdit::keyReleaseEvent(QKeyEvent *e)
225{
226 if ( !e->isAutoRepeat() ) {
227 mFlagKeyPressed = false;
228 }
229
230}
231void KOTimeEdit::setSelect( int from, int to )
232{
233 if ( KOPrefs::instance()->mHightlightDateTimeEdit)
234 lineEdit()->setSelection( from , to );
235}
236
237
238void KOTimeEdit::keyPressEvent(QKeyEvent *e)
239{
240
241 qApp->processEvents();
242 bool hour12Format = ( KOPrefs::instance()->mPreferredTime == 1 );
243 int maxpos = hour12Format?7:5;
244 if ( e->isAutoRepeat() && !mFlagKeyPressed ) {
245 e->ignore();
246 // qDebug(" ignore %d",e->isAutoRepeat() );
247 return;
248 }
249 if (! e->isAutoRepeat() ) {
250 mFlagKeyPressed = true;
251 }
252 // Tap -> Focus Next Widget
253 if ( e->key() == Key_Tab ) {
254 QComboBox::keyPressEvent(e);
255 return;
256 }
257
258 // save Text from QLineEdit and CursorPosition
259 QString text = lineEdit()->text();
260 int cpos = lineEdit()->cursorPosition();
261 // qDebug("cpos %d ", cpos);
262
263 // Switch for arrows, backspace and escape
264 switch(e->key()) {
265 case Key_Escape:
266 lineEdit()->deselect();
267 case Key_Tab:
268 QComboBox::keyPressEvent(e);
269 break;
270 case Key_Up:
271 if ( e->state () == Qt::ControlButton ) {
272 addTime(QTime(0,15,0), false );
273 lineEdit()->setCursorPosition(3);
274 setSelect( 3 , 2 );
275 }
276 else
277 if ( e->state () == Qt::ShiftButton ) {
278 addTime(QTime(1,0,0), false );
279 lineEdit()->setCursorPosition(0);
280 setSelect( 0 , 2 );
281 }
282 else
283 // switch time up, cursor location depend
284 switch (cpos) {
285 case 7:
286 case 6:
287 case 5:
288 if(!hour12Format) {
289 lineEdit()->setCursorPosition(cpos = 4);
290 } else {
291 addTime(QTime(12,0,0), false );
292 setSelect ( 5 , 2 );
293 break;
294 }
295 case 4:
296 addTime(QTime(0,1,0), false );
297 setSelect ( cpos , 1 );
298 break;
299 case 3:
300 addTime(QTime(0,10,0), false );
301 setSelect ( cpos , 1 );
302 break;
303 case 2:
304 lineEdit()->setCursorPosition(--cpos);
305 case 1:
306 case 0:
307 addTime(QTime(1,0,0), false );
308 setSelect ( 0, 2 );
309 break;
310 }
311 break;
312 case Key_Down:
313 if ( e->state () == Qt::ControlButton ) {
314 subTime(QTime(0,15,0), false );
315 lineEdit()->setCursorPosition(3);
316 setSelect( 3 , 2 );
317 }
318 else
319 if ( e->state () == Qt::ShiftButton ) {
320 subTime(QTime(1,0,0), false );
321 lineEdit()->setCursorPosition(0);
322 setSelect( 0 , 2 );
323 }
324 else
325 // switch time down, cursor location depend
326 switch (cpos) {
327 case 7:
328 case 6:
329 case 5:
330 if(!hour12Format) {
331 lineEdit()->setCursorPosition(cpos = 4);
332 } else {
333 subTime(QTime(12,0,0), false );
334 setSelect ( 5 , 2 );
335 break;
336 }
337 case 4:
338 subTime(QTime(0,1,0), false );
339 setSelect ( cpos , 1 );
340 break;
341 case 3:
342 subTime(QTime(0,10,0), false );
343 setSelect ( cpos , 1 );
344 break;
345 case 2:
346 lineEdit()->setCursorPosition(--cpos);
347 case 1:
348 case 0:
349 subTime(QTime(1,0,0), false );
350 setSelect ( 0 , 2 );
351 break;
352 }
353 break;
354 // set cursor to correct place
355 case Key_Left:
356 if ( cpos == 3 )
357 --cpos;
358 if ( cpos > 0) {
359 lineEdit()->setCursorPosition(--cpos);
360 setSelect ( cpos , 1 );
361 }
362 else
363 setSelect ( 0 , 1 );
364 break;
365 // set cursor to correct place
366 case Key_Right:
367 if ( cpos == 1 )
368 ++cpos;
369 if ( cpos < maxpos ) {
370 lineEdit()->setCursorPosition(++cpos);
371 setSelect ( cpos , 1 );
372 }
373 break;
374 // rest
375 case Key_Prior:
376 subTime(QTime(1,0,0));
377 break;
378 case Key_Next:
379 addTime(QTime(1,0,0));
380 break;
381 case Key_Backspace:
382 if ( cpos > 0) {
383 if ( cpos == 3 )
384 --cpos;
385 if ( cpos > 5)
386 cpos = 5;
387 text.at( cpos-1 ) = '0';
388 lineEdit()->setText( text );
389 lineEdit()->setCursorPosition(--cpos);
390 setSelect ( cpos , 1 );
391 changedText();
392 }
393 break;
394 } // switch arrows
395
396 // if cursor at string end, alltext market and keyEvent don't ArrowLeft -> deselect and cpos
397 if( cpos > 4 && lineEdit()->markedText().length() == 5 && e->key() != Key_Left ) {
398 lineEdit()->deselect();
399 cpos = 0;
400 lineEdit()->setCursorPosition(cpos);
401 setSelect(cpos , 1);
402 }
403
404 if ( cpos == 2 ) {
405 lineEdit()->setCursorPosition(++cpos);
406 }
407
408 // num keys when cursorPos preEnd
409 if ( cpos < 5 ) {
410 // switch another keys
411 switch(e->key()) {
412 case Key_Delete:
413 text.at( cpos ) = '0';
414 lineEdit()->setText( text );
415 lineEdit()->setCursorPosition(cpos);
416 setSelect ( cpos , 1 );
417 changedText();
418 break;
419 case Key_9:
420 case Key_8:
421 case Key_7:
422 case Key_6:
423 if ( !(cpos == 1 || cpos == 4) )
424 return;
425 if ( cpos == 1 && text.at( 0 ) > '1')
426 text.at( 0 ) = '1';
427 case Key_5:
428 case Key_4:
429 case Key_3:
430 if ( cpos < 1 )
431 return;
432 if ( hour12Format && cpos == 1 )
433 return;
434 case Key_2:
435 if ( hour12Format && cpos == 0 )
436 return;
437 if ( cpos == 0 && text.at( 1 ) > '3')
438 text.at( 1 ) = '3';
439 case Key_1:
440 case Key_0:
441 if ( hour12Format ) {
442 if ( e->key() == Key_0 && cpos == 1 && text.at( 0 ) == '0' )
443 return;
444 if ( e->key() == Key_0 && cpos == 0 && text.at( 1 ) == '0' )
445 text.at( 1 ) = '1';
446 }
447 text.at( cpos ) = QChar ( e->key() );
448 lineEdit()->setText( text );
449 if ( cpos == 1 )
450 ++cpos;
451 if ( cpos < 5)
452 lineEdit()->setCursorPosition(++cpos);
453 setSelect( cpos , 1 );
454 changedText();
455 break;
456 case Key_Home:
457 lineEdit()->setCursorPosition(0);
458 setSelect( cpos , 1 );
459 break;
460 case Key_End:
461 lineEdit()->setCursorPosition(5);
462 lineEdit()->deselect();
463 break;
464 default:
465// QComboBox::keyPressEvent(e);
466 break;
467 } // switch num keys
468 } else if ( cpos == 5 ) {// if cpos < 5
469 if ( hour12Format ) {
470 if ( e->key() == Key_A ) {
471 text.at( 5 ) = 'a';
472 lineEdit()->setText( text );
473 lineEdit()->setCursorPosition(5);
474
475 } else if ( e->key() == Key_P ) {
476 text.at( 5 ) = 'p';
477 lineEdit()->setText( text );
478 lineEdit()->setCursorPosition(5);
479
480 }
481 }
482 }
483
484
485}
486
487void KOTimeEdit::updateText()
488{
489// kdDebug(5850) << "KOTimeEdit::updateText() " << endl
490 QString s = KGlobal::locale()->formatTime(mTime);
491 // Set the text but without emitting signals, nor losing the cursor position
492 QLineEdit *line = lineEdit();
493 line->blockSignals(true);
494 int pos = line->cursorPosition();
495 // qDebug(" settext *%s* ", s.latin1());
496 line->setText(s);
497 // line->setCursorPosition(pos);
498// line->blockSignals(false);
499
500// kdDebug(5850) << "KOTimeEdit::updateText(): " << s << endl;
501
502 if (!mTime.minute() % 15) {
503 setCurrentItem((mTime.hour()*4)+(mTime.minute()/15));
504 }
505 line->setCursorPosition(pos);
506 line->blockSignals(false);
507
508}
509
510bool KOTimeEdit::inputIsValid() const
511{
512 int cursorPos = lineEdit()->cursorPosition();
513 QString str = currentText();
514 return validator()->validate( str, cursorPos ) == QValidator::Acceptable;
515}
516
517void KOTimeEdit::changedText()
518{
519 //kdDebug(5850) << "KOTimeEdit::changedText()" << endl;
520 if ( inputIsValid() )
521 {
522 int pos = lineEdit()->cursorPosition();
523 mTime = getTime();
524 // updateText();
525 emit timeChanged(mTime);
526 lineEdit()->setCursorPosition(pos);
527 }
528}