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>
43 class KOTimeValidator : public TQValidator
44 {
45 public:
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.
108 KTimeEdit::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 
136 KTimeEdit::~KTimeEdit()
137 {
138 }
139 
140 bool KTimeEdit::hasTime() const
141 {
142  // Can't happen
143  if ( currentText().isEmpty() ) return false;
144  //if ( currentText() == mNoTimeString ) return false;
145 
146  return true; // always
147 }
148 
149 TQTime 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 
168 TQSizePolicy 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 
177 void 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 
188 void 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 
198 void KTimeEdit::hilit(int )
199 {
200  // we don't currently need to do anything here.
201 }
202 
203 void 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 
211 void 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 
236 void 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 
257 void 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 
284 void 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