|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt3Support module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "q3datetimeedit.h" |
|
43 |
|
44 #ifndef QT_NO_DATETIMEEDIT |
|
45 |
|
46 #include <private/q3richtext_p.h> |
|
47 #include "qevent.h" |
|
48 #include "q3rangecontrol.h" |
|
49 #include "qapplication.h" |
|
50 #include "qpixmap.h" |
|
51 #include "qlist.h" |
|
52 #include "qstring.h" |
|
53 #include "qstyle.h" |
|
54 |
|
55 #if defined(Q_WS_WIN) |
|
56 #include "qt_windows.h" |
|
57 #endif |
|
58 |
|
59 QT_BEGIN_NAMESPACE |
|
60 |
|
61 #define QDATETIMEEDIT_HIDDEN_CHAR QLatin1Char('0') |
|
62 |
|
63 class Q_COMPAT_EXPORT QNumberSection |
|
64 { |
|
65 public: |
|
66 QNumberSection(int selStart = 0, int selEnd = 0, bool separat = true, int actual = -1) |
|
67 : selstart(selStart), selend(selEnd), act(actual), sep(separat) |
|
68 {} |
|
69 int selectionStart() const { return selstart; } |
|
70 void setSelectionStart(int s) { selstart = s; } |
|
71 int selectionEnd() const { return selend; } |
|
72 void setSelectionEnd(int s) { selend = s; } |
|
73 int width() const { return selend - selstart; } |
|
74 int index() const { return act; } |
|
75 bool separator() const { return sep; } |
|
76 Q_DUMMY_COMPARISON_OPERATOR(QNumberSection) |
|
77 private: |
|
78 signed int selstart :12; |
|
79 signed int selend :12; |
|
80 signed int act :7; |
|
81 bool sep :1; |
|
82 }; |
|
83 |
|
84 static QString *lDateSep = 0; |
|
85 static QString *lTimeSep = 0; |
|
86 static bool lAMPM = false; |
|
87 static QString *lAM = 0; |
|
88 static QString *lPM = 0; |
|
89 static Q3DateEdit::Order lOrder = Q3DateEdit::YMD; |
|
90 static int refcount = 0; |
|
91 |
|
92 static void cleanup() |
|
93 { |
|
94 delete lDateSep; |
|
95 lDateSep = 0; |
|
96 delete lTimeSep; |
|
97 lTimeSep = 0; |
|
98 delete lAM; |
|
99 lAM = 0; |
|
100 delete lPM; |
|
101 lPM = 0; |
|
102 } |
|
103 |
|
104 /*! |
|
105 \internal |
|
106 try to get the order of DMY and the date/time separator from the locale settings |
|
107 */ |
|
108 static void readLocaleSettings() |
|
109 { |
|
110 int dpos, mpos, ypos; |
|
111 cleanup(); |
|
112 |
|
113 lDateSep = new QString(); |
|
114 lTimeSep = new QString(); |
|
115 |
|
116 #if defined(Q_WS_WIN) |
|
117 wchar_t data[10]; |
|
118 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, data, 10); |
|
119 *lDateSep = QString::fromWCharArray(data); |
|
120 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, data, 10); |
|
121 *lTimeSep = QString::fromWCharArray(data); |
|
122 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, data, 10); |
|
123 lAMPM = QString::fromWCharArray(data).toInt() == 0; |
|
124 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, data, 10); |
|
125 QString am = QString::fromWCharArray(data); |
|
126 if (!am.isEmpty()) |
|
127 lAM = new QString(am); |
|
128 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, data, 10); |
|
129 QString pm = QString::fromWCharArray(data); |
|
130 if (!pm.isEmpty() ) |
|
131 lPM = new QString(pm); |
|
132 #else |
|
133 *lDateSep = QLatin1Char('-'); |
|
134 *lTimeSep = QLatin1Char(':'); |
|
135 #endif |
|
136 QString d = QDate(1999, 11, 22).toString(Qt::LocalDate); |
|
137 dpos = d.indexOf(QLatin1String("22")); |
|
138 mpos = d.indexOf(QLatin1String("11")); |
|
139 ypos = d.indexOf(QLatin1String("99")); |
|
140 if (dpos > -1 && mpos > -1 && ypos > -1) { |
|
141 // test for DMY, MDY, YMD, YDM |
|
142 if (dpos < mpos && mpos < ypos) { |
|
143 lOrder = Q3DateEdit::DMY; |
|
144 } else if (mpos < dpos && dpos < ypos) { |
|
145 lOrder = Q3DateEdit::MDY; |
|
146 } else if (ypos < mpos && mpos < dpos) { |
|
147 lOrder = Q3DateEdit::YMD; |
|
148 } else if (ypos < dpos && dpos < mpos) { |
|
149 lOrder = Q3DateEdit::YDM; |
|
150 } else { |
|
151 // cannot determine the dateformat - use the default |
|
152 return; |
|
153 } |
|
154 |
|
155 // this code needs to change if new formats are added |
|
156 |
|
157 #ifndef Q_WS_WIN |
|
158 QString sep = d.mid(qMin(dpos, mpos) + 2, QABS(dpos - mpos) - 2); |
|
159 if (d.count(sep) == 2) { |
|
160 *lDateSep = sep; |
|
161 } |
|
162 #endif |
|
163 } |
|
164 |
|
165 #ifndef Q_WS_WIN |
|
166 QString t = QTime(11, 22, 33).toString(Qt::LocalDate); |
|
167 dpos = t.indexOf(QLatin1String("11")); |
|
168 mpos = t.indexOf(QLatin1String("22")); |
|
169 ypos = t.indexOf(QLatin1String("33")); |
|
170 // We only allow hhmmss |
|
171 if (dpos > -1 && dpos < mpos && mpos < ypos) { |
|
172 QString sep = t.mid(dpos + 2, mpos - dpos - 2); |
|
173 if (sep == t.mid(mpos + 2, ypos - mpos - 2)) { |
|
174 *lTimeSep = sep; |
|
175 } |
|
176 } |
|
177 #endif |
|
178 } |
|
179 |
|
180 static Q3DateEdit::Order localOrder() { |
|
181 if (!lDateSep) { |
|
182 readLocaleSettings(); |
|
183 } |
|
184 return lOrder; |
|
185 } |
|
186 |
|
187 static QString localDateSep() { |
|
188 if (!lDateSep) { |
|
189 readLocaleSettings(); |
|
190 } |
|
191 return *lDateSep; |
|
192 } |
|
193 |
|
194 static QString localTimeSep() { |
|
195 if (!lTimeSep) { |
|
196 readLocaleSettings(); |
|
197 } |
|
198 return *lTimeSep; |
|
199 } |
|
200 |
|
201 class Q3DateTimeEditorPrivate |
|
202 { |
|
203 public: |
|
204 Q3DateTimeEditorPrivate() |
|
205 : frm(true), |
|
206 parag(new Q3TextParagraph(0, 0, 0, false)), |
|
207 focusSec(0) |
|
208 { |
|
209 parag->formatter()->setWrapEnabled(false); |
|
210 cursor = new Q3TextCursor(0); |
|
211 cursor->setParagraph(parag); |
|
212 offset = 0; |
|
213 sep = localDateSep(); |
|
214 refcount++; |
|
215 } |
|
216 ~Q3DateTimeEditorPrivate() |
|
217 { |
|
218 delete parag; |
|
219 delete cursor; |
|
220 if (!--refcount) |
|
221 cleanup(); |
|
222 } |
|
223 |
|
224 void appendSection(const QNumberSection& sec) |
|
225 { |
|
226 sections.append(sec); |
|
227 |
|
228 } |
|
229 void clearSections() |
|
230 { |
|
231 sections.clear(); |
|
232 } |
|
233 void setSectionSelection(int sec, int selstart, int selend) |
|
234 { |
|
235 if (sec < 0 || sec >= sections.count()) |
|
236 return; |
|
237 sections[sec].setSelectionStart(selstart); |
|
238 sections[sec].setSelectionEnd(selend); |
|
239 } |
|
240 uint sectionCount() const { return (uint)sections.count(); } |
|
241 void setSeparator(const QString& s) { sep = s; } |
|
242 QString separator() const { return sep; } |
|
243 |
|
244 void setFrame(bool f) { frm = f; } |
|
245 bool frame() const { return frm; } |
|
246 |
|
247 int focusSection() const { return focusSec; } |
|
248 int section(const QPoint& p) |
|
249 { |
|
250 cursor->place(p + QPoint(offset, 0), parag); |
|
251 int idx = cursor->index(); |
|
252 for (int i = 0; i < sections.count(); ++i) { |
|
253 if (idx >= sections[i].selectionStart() && |
|
254 idx <= sections[i].selectionEnd()) |
|
255 return i; |
|
256 } |
|
257 return -1; |
|
258 } |
|
259 QNumberSection section(int idx) const |
|
260 { |
|
261 return sections[idx]; |
|
262 } |
|
263 bool setFocusSection(int idx) |
|
264 { |
|
265 if (idx > (int)sections.count()-1 || idx < 0) |
|
266 return false; |
|
267 if (idx != focusSec) { |
|
268 focusSec = idx; |
|
269 applyFocusSelection(); |
|
270 return true; |
|
271 } |
|
272 return false; |
|
273 } |
|
274 |
|
275 bool inSectionSelection(int idx) |
|
276 { |
|
277 for (int i = 0; i < sections.count(); ++i) { |
|
278 if (idx >= sections[i].selectionStart() && |
|
279 idx <= sections[i].selectionEnd()) |
|
280 return true; |
|
281 } |
|
282 return false; |
|
283 } |
|
284 |
|
285 void paint(const QString& txt, bool focus, QPainter& p, |
|
286 const QPalette&pal, const QRect& rect, QStyle *style) |
|
287 { |
|
288 int fw = 0; |
|
289 if (frm) |
|
290 fw = style->pixelMetric(QStyle::PM_DefaultFrameWidth); |
|
291 |
|
292 parag->truncate(0); |
|
293 parag->append(txt); |
|
294 if (!focus) |
|
295 parag->removeSelection(Q3TextDocument::Standard); |
|
296 else { |
|
297 applyFocusSelection(); |
|
298 } |
|
299 |
|
300 /* color all QDATETIMEEDIT_HIDDEN_CHAR chars to background color */ |
|
301 Q3TextFormat *fb = parag->formatCollection()->format(p.font(), |
|
302 pal.base().color()); |
|
303 Q3TextFormat *nf = parag->formatCollection()->format(p.font(), |
|
304 pal.text().color()); |
|
305 for (int i = 0; i < txt.length(); ++i) { |
|
306 parag->setFormat(i, 1, nf); |
|
307 if (inSectionSelection(i)) |
|
308 continue; |
|
309 if (txt.at(i) == QDATETIMEEDIT_HIDDEN_CHAR) |
|
310 parag->setFormat(i, 1, fb); |
|
311 else |
|
312 parag->setFormat(i, 1, nf); |
|
313 } |
|
314 fb->removeRef(); |
|
315 nf->removeRef(); |
|
316 |
|
317 QRect r(rect.x(), rect.y(), rect.width() - 2 * (2 + fw), rect.height()); |
|
318 parag->pseudoDocument()->docRect = r; |
|
319 parag->invalidate(0); |
|
320 parag->format(); |
|
321 |
|
322 int xoff = 2 + fw - offset; |
|
323 int yoff = (rect.height() - parag->rect().height() + 1) / 2; |
|
324 if (yoff < 0) |
|
325 yoff = 0; |
|
326 |
|
327 p.translate(xoff, yoff); |
|
328 parag->paint(p, pal, 0, true); |
|
329 if (frm) |
|
330 p.translate(-xoff, -yoff); |
|
331 } |
|
332 |
|
333 void resize(const QSize& size) { sz = size; } |
|
334 |
|
335 int mapSection(int sec) |
|
336 { |
|
337 return (sec >= 0 && sec < sections.count() ? sections[sec].index() : -1); |
|
338 } |
|
339 |
|
340 protected: |
|
341 void applyFocusSelection() |
|
342 { |
|
343 if (focusSec > -1 && focusSec < sections.count()) { |
|
344 int selstart = sections[focusSec].selectionStart(); |
|
345 int selend = sections[focusSec].selectionEnd(); |
|
346 parag->setSelection(Q3TextDocument::Standard, selstart, selend); |
|
347 parag->format(); |
|
348 if (parag->at(selstart)->x < offset || |
|
349 parag->at(selend)->x + parag->string()->width(selend) > offset + sz.width()) { |
|
350 offset = parag->at(selstart)->x; |
|
351 } |
|
352 } |
|
353 } |
|
354 private: |
|
355 bool frm; |
|
356 Q3TextParagraph *parag; |
|
357 Q3TextCursor *cursor; |
|
358 QSize sz; |
|
359 int focusSec; |
|
360 QList< QNumberSection > sections; |
|
361 QString sep; |
|
362 int offset; |
|
363 }; |
|
364 |
|
365 class Q3DateTimeEditor : public QWidget |
|
366 { |
|
367 Q_OBJECT |
|
368 public: |
|
369 Q3DateTimeEditor(Q3DateTimeEditBase *widget, QWidget *parent, const char* name=0); |
|
370 ~Q3DateTimeEditor(); |
|
371 |
|
372 void setControlWidget(Q3DateTimeEditBase * widget); |
|
373 Q3DateTimeEditBase * controlWidget() const; |
|
374 |
|
375 void setSeparator(const QString& s); |
|
376 QString separator() const; |
|
377 |
|
378 int focusSection() const; |
|
379 bool setFocusSection(int s); |
|
380 void appendSection(const QNumberSection& sec); |
|
381 void clearSections(); |
|
382 void setSectionSelection(int sec, int selstart, int selend); |
|
383 bool eventFilter(QObject *o, QEvent *e); |
|
384 int sectionAt(const QPoint &p); |
|
385 int mapSection(int sec); |
|
386 |
|
387 protected: |
|
388 void init(); |
|
389 bool event(QEvent *e); |
|
390 void resizeEvent(QResizeEvent *); |
|
391 void paintEvent(QPaintEvent *); |
|
392 void mousePressEvent(QMouseEvent *e); |
|
393 |
|
394 private: |
|
395 Q3DateTimeEditBase* cw; |
|
396 Q3DateTimeEditorPrivate* d; |
|
397 }; |
|
398 |
|
399 class QDateTimeSpinWidget : public Q3SpinWidget |
|
400 { |
|
401 Q_OBJECT |
|
402 public: |
|
403 QDateTimeSpinWidget(QWidget *parent, const char *name) |
|
404 : Q3SpinWidget(parent, name) |
|
405 { |
|
406 } |
|
407 |
|
408 void changeEvent(QEvent *e) |
|
409 { |
|
410 if (e->type() == QEvent::EnabledChange && isEnabled()) { |
|
411 Q3DateEdit *de = qobject_cast<Q3DateEdit*>(parentWidget()); |
|
412 if (de) { |
|
413 setUpEnabled(de->date() < de->maxValue()); |
|
414 setDownEnabled(de->date() > de->minValue()); |
|
415 } else { |
|
416 setUpEnabled(true); |
|
417 setDownEnabled(true); |
|
418 } |
|
419 } |
|
420 } |
|
421 void enabledChange(bool notenabled) |
|
422 { |
|
423 Q3DateEdit *de = qobject_cast<Q3DateEdit*>(parentWidget()); |
|
424 if (de && !notenabled) { |
|
425 setUpEnabled(de->date() < de->maxValue()); |
|
426 setDownEnabled(de->date() > de->minValue()); |
|
427 } else { |
|
428 setUpEnabled(!notenabled); |
|
429 setDownEnabled(!notenabled); |
|
430 } |
|
431 } |
|
432 |
|
433 |
|
434 protected: |
|
435 #ifndef QT_NO_WHEELEVENT |
|
436 void wheelEvent(QWheelEvent *e) |
|
437 { |
|
438 Q3DateTimeEditor *editor = qobject_cast<Q3DateTimeEditor*>(editWidget()); |
|
439 Q_ASSERT(editor); |
|
440 if (!editor) |
|
441 return; |
|
442 |
|
443 int section = editor->sectionAt(e->pos()); |
|
444 editor->setFocusSection(section); |
|
445 |
|
446 if (section == -1) |
|
447 return; |
|
448 Q3SpinWidget::wheelEvent(e); |
|
449 } |
|
450 #endif |
|
451 }; |
|
452 |
|
453 /*! |
|
454 Constructs an empty datetime editor with parent \a parent and |
|
455 called \a name. |
|
456 */ |
|
457 Q3DateTimeEditor::Q3DateTimeEditor(Q3DateTimeEditBase *widget, QWidget *parent, const char * name) |
|
458 : QWidget(parent, name) |
|
459 { |
|
460 d = new Q3DateTimeEditorPrivate(); |
|
461 cw = widget; |
|
462 init(); |
|
463 } |
|
464 |
|
465 /*! |
|
466 Destroys the object and frees any allocated resources. |
|
467 */ |
|
468 |
|
469 Q3DateTimeEditor::~Q3DateTimeEditor() |
|
470 { |
|
471 delete d; |
|
472 } |
|
473 |
|
474 /*! \internal |
|
475 |
|
476 */ |
|
477 |
|
478 void Q3DateTimeEditor::init() |
|
479 { |
|
480 setBackgroundRole(QPalette::Base); |
|
481 setFocusSection(-1); |
|
482 installEventFilter(this); |
|
483 setFocusPolicy(Qt::WheelFocus); |
|
484 } |
|
485 |
|
486 |
|
487 /*! \reimp |
|
488 |
|
489 */ |
|
490 |
|
491 bool Q3DateTimeEditor::event(QEvent *e) |
|
492 { |
|
493 if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut) { |
|
494 if (e->type() == QEvent::FocusOut) |
|
495 qApp->sendEvent(cw, e); |
|
496 update(rect()); |
|
497 } else if (e->type() == QEvent::ShortcutOverride) { |
|
498 QKeyEvent* ke = (QKeyEvent*) e; |
|
499 switch (ke->key()) { |
|
500 case Qt::Key_Delete: |
|
501 case Qt::Key_Backspace: |
|
502 case Qt::Key_Up: |
|
503 case Qt::Key_Down: |
|
504 case Qt::Key_Left: |
|
505 case Qt::Key_Right: |
|
506 ke->accept(); |
|
507 default: |
|
508 break; |
|
509 } |
|
510 } |
|
511 return QWidget::event(e); |
|
512 } |
|
513 |
|
514 /*! \reimp |
|
515 |
|
516 */ |
|
517 |
|
518 void Q3DateTimeEditor::resizeEvent(QResizeEvent *e) |
|
519 { |
|
520 d->resize(e->size()); |
|
521 QWidget::resizeEvent(e); |
|
522 } |
|
523 |
|
524 |
|
525 /*! \reimp |
|
526 |
|
527 */ |
|
528 |
|
529 void Q3DateTimeEditor::paintEvent(QPaintEvent *) |
|
530 { |
|
531 QString txt; |
|
532 for (uint i = 0; i < d->sectionCount(); ++i) { |
|
533 txt += cw->sectionFormattedText(i); |
|
534 if (i < d->sectionCount()-1) { |
|
535 if (d->section(i+1).separator()) |
|
536 txt += d->separator(); |
|
537 else |
|
538 txt += QLatin1Char(' '); |
|
539 } |
|
540 } |
|
541 |
|
542 QPainter p(this); |
|
543 const QBrush &bg = palette().brush(isEnabled() ? QPalette::Base : QPalette::Window); |
|
544 p.fillRect(0, 0, width(), height(), bg); |
|
545 d->paint(txt, hasFocus(), p, palette(), rect(), style()); |
|
546 } |
|
547 |
|
548 |
|
549 /*! |
|
550 Returns the section index at point \a p. |
|
551 */ |
|
552 int Q3DateTimeEditor::sectionAt(const QPoint &p) |
|
553 { |
|
554 return d->section(p); |
|
555 } |
|
556 |
|
557 int Q3DateTimeEditor::mapSection(int sec) |
|
558 { |
|
559 return d->mapSection(sec); |
|
560 } |
|
561 |
|
562 |
|
563 /*! \reimp |
|
564 |
|
565 */ |
|
566 |
|
567 void Q3DateTimeEditor::mousePressEvent(QMouseEvent *e) |
|
568 { |
|
569 QPoint p(e->pos().x(), 0); |
|
570 int sec = sectionAt(p); |
|
571 if (sec != -1) { |
|
572 cw->setFocusSection(sec); |
|
573 repaint(rect()); |
|
574 } |
|
575 } |
|
576 |
|
577 /*! \reimp |
|
578 |
|
579 */ |
|
580 bool Q3DateTimeEditor::eventFilter(QObject *o, QEvent *e) |
|
581 { |
|
582 if (o == this) { |
|
583 if (e->type() == QEvent::KeyPress) { |
|
584 QKeyEvent *ke = (QKeyEvent*)e; |
|
585 switch (ke->key()) { |
|
586 case Qt::Key_Right: |
|
587 if (d->focusSection() < (int)d->sectionCount()-1) { |
|
588 if (cw->setFocusSection(focusSection()+1)) |
|
589 repaint(rect()); |
|
590 } |
|
591 return true; |
|
592 case Qt::Key_Left: |
|
593 if (d->focusSection() > 0) { |
|
594 if (cw->setFocusSection(focusSection()-1)) |
|
595 repaint(rect()); |
|
596 } |
|
597 return true; |
|
598 case Qt::Key_Up: |
|
599 cw->stepUp(); |
|
600 return true; |
|
601 case Qt::Key_Down: |
|
602 cw->stepDown(); |
|
603 return true; |
|
604 case Qt::Key_Backspace: |
|
605 if (qobject_cast<Q3DateEdit*>(cw)) |
|
606 ((Q3DateEdit*)cw)->removeFirstNumber(d->focusSection()); |
|
607 else if (qobject_cast<Q3TimeEdit*>(cw)) |
|
608 ((Q3TimeEdit*)cw)->removeFirstNumber(d->focusSection()); |
|
609 return true; |
|
610 case Qt::Key_Delete: |
|
611 cw->removeLastNumber(d->focusSection()); |
|
612 return true; |
|
613 case Qt::Key_Tab: |
|
614 case Qt::Key_BackTab: { |
|
615 if (ke->state() == Qt::ControlButton) |
|
616 return false; |
|
617 QWidget *w = this; |
|
618 bool hadDateEdit = false; |
|
619 while (w) { |
|
620 if (qobject_cast<QDateTimeSpinWidget*>(w) || qobject_cast<Q3DateTimeEdit*>(w)) |
|
621 break; |
|
622 hadDateEdit = hadDateEdit || qobject_cast<Q3DateEdit*>(w); |
|
623 w = w->parentWidget(); |
|
624 } |
|
625 if (w) { |
|
626 if (!qobject_cast<Q3DateTimeEdit*>(w)) { |
|
627 w = w->parentWidget(); |
|
628 } else { |
|
629 Q3DateTimeEdit *ed = (Q3DateTimeEdit*)w; |
|
630 if (hadDateEdit && ke->key() == Qt::Key_Tab) { |
|
631 ed->timeEdit()->setFocus(); |
|
632 return true; |
|
633 } else if (!hadDateEdit && ke->key() == Qt::Key_BackTab) { |
|
634 ed->dateEdit()->setFocus(); |
|
635 return true; |
|
636 } else { |
|
637 while (w && !qobject_cast<Q3DateTimeEdit*>(w)) |
|
638 w = w->parentWidget(); |
|
639 } |
|
640 } |
|
641 qApp->sendEvent(w, e); |
|
642 return true; |
|
643 } |
|
644 } break; |
|
645 default: |
|
646 QString txt = ke->text().toLower(); |
|
647 if (!txt.isEmpty() && !separator().isEmpty() && txt[0] == separator()[0]) { |
|
648 // do the same thing as KEY_RIGHT when the user presses the separator key |
|
649 if (d->focusSection() < 2) { |
|
650 if (cw->setFocusSection(focusSection()+1)) |
|
651 repaint(rect()); |
|
652 } |
|
653 return true; |
|
654 } else if (!txt.isEmpty() && qobject_cast<Q3TimeEdit*>(cw) && focusSection() == (int) d->sectionCount()-1) { |
|
655 // the first character of the AM/PM indicator toggles if the section has focus |
|
656 Q3TimeEdit *te = (Q3TimeEdit*)cw; |
|
657 QTime time = te->time(); |
|
658 if (lAMPM && lAM && lPM && (te->display()&Q3TimeEdit::AMPM)) { |
|
659 if (txt[0] == (*lAM).toLower()[0] && time.hour() >= 12) { |
|
660 time.setHMS(time.hour()-12, time.minute(), time.second(), time.msec()); |
|
661 te->setTime(time); |
|
662 } else if (txt[0] == (*lPM).toLower()[0] && time.hour() < 12) { |
|
663 time.setHMS(time.hour()+12, time.minute(), time.second(), time.msec()); |
|
664 te->setTime(time); |
|
665 } |
|
666 } |
|
667 } |
|
668 |
|
669 int num = txt[0].digitValue(); |
|
670 if (num != -1) { |
|
671 cw->addNumber(d->focusSection(), num); |
|
672 return true; |
|
673 } |
|
674 } |
|
675 } |
|
676 } |
|
677 return false; |
|
678 } |
|
679 |
|
680 |
|
681 /*! |
|
682 Appends the number section \a sec to the editor. |
|
683 */ |
|
684 |
|
685 void Q3DateTimeEditor::appendSection(const QNumberSection& sec) |
|
686 { |
|
687 d->appendSection(sec); |
|
688 } |
|
689 |
|
690 /*! |
|
691 Removes all sections from the editor. |
|
692 */ |
|
693 |
|
694 void Q3DateTimeEditor::clearSections() |
|
695 { |
|
696 d->clearSections(); |
|
697 } |
|
698 |
|
699 /*! |
|
700 Sets the selection of \a sec to start at \a selstart and end at \a |
|
701 selend. |
|
702 */ |
|
703 |
|
704 void Q3DateTimeEditor::setSectionSelection(int sec, int selstart, int selend) |
|
705 { |
|
706 d->setSectionSelection(sec, selstart, selend); |
|
707 } |
|
708 |
|
709 /*! |
|
710 Sets the separator for all numbered sections to \a s. Note that |
|
711 currently, only the first character of \a s is used. |
|
712 */ |
|
713 |
|
714 void Q3DateTimeEditor::setSeparator(const QString& s) |
|
715 { |
|
716 d->setSeparator(s); |
|
717 update(); |
|
718 } |
|
719 |
|
720 |
|
721 /*! |
|
722 Returns the editor's separator. |
|
723 */ |
|
724 |
|
725 QString Q3DateTimeEditor::separator() const |
|
726 { |
|
727 return d->separator(); |
|
728 } |
|
729 |
|
730 /*! |
|
731 Returns the number of the section that has focus. |
|
732 */ |
|
733 |
|
734 int Q3DateTimeEditor::focusSection() const |
|
735 { |
|
736 return d->focusSection(); |
|
737 } |
|
738 |
|
739 |
|
740 /*! |
|
741 Sets the focus to section \a sec. If \a sec does not exist, |
|
742 nothing happens. |
|
743 */ |
|
744 |
|
745 bool Q3DateTimeEditor::setFocusSection(int sec) |
|
746 { |
|
747 return d->setFocusSection(sec); |
|
748 } |
|
749 |
|
750 /*! |
|
751 \class Q3DateTimeEditBase |
|
752 \brief The Q3DateTimeEditBase class provides an abstraction for date and edit editors. |
|
753 |
|
754 \compat |
|
755 |
|
756 Small abstract class that provides some functions that are common |
|
757 for both Q3DateEdit and Q3TimeEdit. It is used internally by |
|
758 Q3DateTimeEditor. |
|
759 */ |
|
760 |
|
761 /*! |
|
762 \fn Q3DateTimeEditBase::Q3DateTimeEditBase(QWidget *, const char*) |
|
763 \internal |
|
764 */ |
|
765 |
|
766 /*! |
|
767 \fn Q3DateTimeEditBase::setFocusSection(int) |
|
768 \internal |
|
769 */ |
|
770 |
|
771 /*! \fn QString Q3DateTimeEditBase::sectionFormattedText(int sec) |
|
772 \internal |
|
773 |
|
774 Pure virtual function which returns the formatted text of section \a |
|
775 sec. |
|
776 |
|
777 */ |
|
778 |
|
779 /*! \fn void Q3DateTimeEditBase::stepUp() |
|
780 \internal |
|
781 |
|
782 Pure virtual slot which is called whenever the user increases the |
|
783 number in a section by pressing the widget's arrow buttons or the |
|
784 keyboard's arrow keys. |
|
785 */ |
|
786 |
|
787 /*! \fn void Q3DateTimeEditBase::stepDown() |
|
788 \internal |
|
789 |
|
790 Pure virtual slot which is called whenever the user decreases the |
|
791 number in a section by pressing the widget's arrow buttons or the |
|
792 keyboard's arrow keys. |
|
793 |
|
794 */ |
|
795 |
|
796 /*! \fn void Q3DateTimeEditBase::addNumber(int sec, int num) |
|
797 \internal |
|
798 |
|
799 Pure virtual function which is called whenever the user types a number. |
|
800 \a sec indicates the section where the number should be added. \a |
|
801 num is the number that was pressed. |
|
802 */ |
|
803 |
|
804 /*! \fn void Q3DateTimeEditBase::removeLastNumber(int sec) |
|
805 \internal |
|
806 |
|
807 Pure virtual function which is called whenever the user tries to |
|
808 remove the last number from \a sec by pressing the delete key. |
|
809 */ |
|
810 |
|
811 //////////////// |
|
812 |
|
813 class Q3DateEditPrivate |
|
814 { |
|
815 public: |
|
816 int y; |
|
817 int m; |
|
818 int d; |
|
819 // remembers the last entry for the day. |
|
820 // if the day is 31 and you cycle through the months, |
|
821 // the day will be 31 again if you reach a month with 31 days |
|
822 // otherwise it will be the highest day in the month |
|
823 int dayCache; |
|
824 int yearSection; |
|
825 int monthSection; |
|
826 int daySection; |
|
827 Q3DateEdit::Order ord; |
|
828 bool overwrite; |
|
829 bool adv; |
|
830 int timerId; |
|
831 bool typing; |
|
832 QDate min; |
|
833 QDate max; |
|
834 bool changed; |
|
835 Q3DateTimeEditor *ed; |
|
836 Q3SpinWidget *controls; |
|
837 }; |
|
838 |
|
839 |
|
840 /*! |
|
841 \class Q3DateEdit |
|
842 \brief The Q3DateEdit class provides a date editor. |
|
843 |
|
844 \compat |
|
845 |
|
846 Q3DateEdit allows the user to edit dates by using the keyboard or |
|
847 the arrow keys to increase/decrease date values. The arrow keys |
|
848 can be used to move from section to section within the Q3DateEdit |
|
849 box. Dates appear in accordance with the local date/time settings |
|
850 or in year, month, day order if the system doesn't provide this |
|
851 information. It is recommended that the Q3DateEdit be initialised |
|
852 with a date, e.g. |
|
853 |
|
854 \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 0 |
|
855 |
|
856 Here we've created a new Q3DateEdit object initialised with today's |
|
857 date and restricted the valid date range to today plus or minus |
|
858 365 days. We've set the order to month, day, year. If the auto |
|
859 advance property is true (as we've set it here) when the user |
|
860 completes a section of the date, e.g. enters two digits for the |
|
861 month, they are automatically taken to the next section. |
|
862 |
|
863 The maximum and minimum values for a date value in the date editor |
|
864 default to the maximum and minimum values for a QDate. You can |
|
865 change this by calling setMinValue(), setMaxValue() or setRange(). |
|
866 |
|
867 Terminology: A Q3DateEdit widget comprises three 'sections', one |
|
868 each for the year, month and day. You can change the separator |
|
869 character using Q3DateTimeEditor::setSeparator(), by default the |
|
870 separator will be taken from the systems settings. If that is |
|
871 not possible, it defaults to "-". |
|
872 |
|
873 \img datetimewidgets.png Date Time Widgets |
|
874 |
|
875 \sa QDate Q3TimeEdit Q3DateTimeEdit |
|
876 */ |
|
877 |
|
878 /*! |
|
879 \enum Q3DateEdit::Order |
|
880 |
|
881 This enum defines the order in which the sections that comprise a |
|
882 date appear. |
|
883 |
|
884 \value MDY month-day-year |
|
885 \value DMY day-month-year |
|
886 \value YMD year-month-day (the default) |
|
887 \omitvalue YDM |
|
888 */ |
|
889 |
|
890 /*! |
|
891 \enum Q3TimeEdit::Display |
|
892 |
|
893 This enum defines the sections that comprise a time |
|
894 |
|
895 \value Hours The hours section |
|
896 \value Minutes The minutes section |
|
897 \value Seconds The seconds section |
|
898 \value AMPM The AM/PM section |
|
899 |
|
900 The values can be or'ed together to show any combination. |
|
901 */ |
|
902 |
|
903 /*! |
|
904 Constructs an empty date editor which is a child of \a parent and |
|
905 called name \a name. |
|
906 */ |
|
907 |
|
908 Q3DateEdit::Q3DateEdit(QWidget * parent, const char * name) |
|
909 : Q3DateTimeEditBase(parent, name) |
|
910 { |
|
911 init(); |
|
912 updateButtons(); |
|
913 } |
|
914 |
|
915 /*! |
|
916 \overload |
|
917 |
|
918 Constructs a date editor with the initial value \a date, parent \a |
|
919 parent and called \a name. |
|
920 |
|
921 The date editor is initialized with \a date. |
|
922 */ |
|
923 |
|
924 Q3DateEdit::Q3DateEdit(const QDate& date, QWidget * parent, const char * name) |
|
925 : Q3DateTimeEditBase(parent, name) |
|
926 { |
|
927 init(); |
|
928 setDate(date); |
|
929 } |
|
930 |
|
931 /*! \internal |
|
932 */ |
|
933 void Q3DateEdit::init() |
|
934 { |
|
935 d = new Q3DateEditPrivate(); |
|
936 d->controls = new QDateTimeSpinWidget(this, 0); |
|
937 d->ed = new Q3DateTimeEditor(this, d->controls); |
|
938 d->controls->setEditWidget(d->ed); |
|
939 setFocusProxy(d->ed); |
|
940 connect(d->controls, SIGNAL(stepUpPressed()), SLOT(stepUp())); |
|
941 connect(d->controls, SIGNAL(stepDownPressed()), SLOT(stepDown())); |
|
942 connect(this, SIGNAL(valueChanged(QDate)), SLOT(updateButtons())); |
|
943 d->ed->appendSection(QNumberSection(0,4)); |
|
944 d->ed->appendSection(QNumberSection(5,7)); |
|
945 d->ed->appendSection(QNumberSection(8,10)); |
|
946 |
|
947 d->yearSection = -1; |
|
948 d->monthSection = -1; |
|
949 d->daySection = -1; |
|
950 |
|
951 d->y = 0; |
|
952 d->m = 0; |
|
953 d->d = 0; |
|
954 d->dayCache = 0; |
|
955 setOrder(localOrder()); |
|
956 setFocusSection(0); |
|
957 d->overwrite = true; |
|
958 d->adv = false; |
|
959 d->timerId = 0; |
|
960 d->typing = false; |
|
961 d->min = QDate(1752, 9, 14); |
|
962 d->max = QDate(8000, 12, 31); |
|
963 d->changed = false; |
|
964 |
|
965 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); |
|
966 |
|
967 refcount++; |
|
968 } |
|
969 |
|
970 /*! |
|
971 Destroys the object and frees any allocated resources. |
|
972 */ |
|
973 |
|
974 Q3DateEdit::~Q3DateEdit() |
|
975 { |
|
976 delete d; |
|
977 if (!--refcount) |
|
978 cleanup(); |
|
979 } |
|
980 |
|
981 /*! |
|
982 \property Q3DateEdit::minValue |
|
983 |
|
984 \brief the editor's minimum value |
|
985 |
|
986 Setting the minimum date value is equivalent to calling |
|
987 Q3DateEdit::setRange(\e d, maxValue()), where \e d is the minimum |
|
988 date. The default minimum date is 1752-09-14. |
|
989 |
|
990 \sa maxValue setRange() |
|
991 */ |
|
992 |
|
993 QDate Q3DateEdit::minValue() const |
|
994 { |
|
995 return d->min; |
|
996 } |
|
997 |
|
998 /*! |
|
999 \property Q3DateEdit::maxValue |
|
1000 |
|
1001 \brief the editor's maximum value |
|
1002 |
|
1003 Setting the maximum date value for the editor is equivalent to |
|
1004 calling Q3DateEdit::setRange(minValue(), \e d), where \e d is the |
|
1005 maximum date. The default maximum date is 8000-12-31. |
|
1006 |
|
1007 \sa minValue setRange() |
|
1008 */ |
|
1009 |
|
1010 QDate Q3DateEdit::maxValue() const |
|
1011 { |
|
1012 return d->max; |
|
1013 } |
|
1014 |
|
1015 |
|
1016 /*! |
|
1017 Sets the valid input range for the editor to be from \a min to \a |
|
1018 max inclusive. If \a min is invalid no minimum date will be set. |
|
1019 Similarly, if \a max is invalid no maximum date will be set. |
|
1020 */ |
|
1021 |
|
1022 void Q3DateEdit::setRange(const QDate& min, const QDate& max) |
|
1023 { |
|
1024 if (min.isValid()) |
|
1025 d->min = min; |
|
1026 if (max.isValid()) |
|
1027 d->max = max; |
|
1028 } |
|
1029 |
|
1030 /*! |
|
1031 Sets the separator to \a s. Note that currently only the first |
|
1032 character of \a s is used. |
|
1033 */ |
|
1034 |
|
1035 void Q3DateEdit::setSeparator(const QString& s) |
|
1036 { |
|
1037 d->ed->setSeparator(s); |
|
1038 } |
|
1039 |
|
1040 /*! |
|
1041 Returns the editor's separator. |
|
1042 */ |
|
1043 |
|
1044 QString Q3DateEdit::separator() const |
|
1045 { |
|
1046 return d->ed->separator(); |
|
1047 } |
|
1048 |
|
1049 |
|
1050 /*! |
|
1051 Enables/disables the push buttons according to the min/max date |
|
1052 for this widget. |
|
1053 */ |
|
1054 |
|
1055 void Q3DateEdit::updateButtons() |
|
1056 { |
|
1057 if (!isEnabled()) |
|
1058 return; |
|
1059 |
|
1060 bool upEnabled = date() < maxValue(); |
|
1061 bool downEnabled = date() > minValue(); |
|
1062 |
|
1063 d->controls->setUpEnabled(upEnabled); |
|
1064 d->controls->setDownEnabled(downEnabled); |
|
1065 } |
|
1066 |
|
1067 /*! \reimp |
|
1068 */ |
|
1069 void Q3DateEdit::resizeEvent(QResizeEvent *) |
|
1070 { |
|
1071 d->controls->resize(width(), height()); |
|
1072 } |
|
1073 |
|
1074 /*! \reimp |
|
1075 |
|
1076 */ |
|
1077 QSize Q3DateEdit::sizeHint() const |
|
1078 { |
|
1079 ensurePolished(); |
|
1080 QFontMetrics fm(font()); |
|
1081 int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this); |
|
1082 int h = qMax(fm.lineSpacing(), 14) + 2; |
|
1083 int w = 2 + fm.width(QLatin1Char('9')) * 8 + fm.width(d->ed->separator()) * 2 + d->controls->upRect().width() + fw * 4; |
|
1084 |
|
1085 return QSize(w, qMax(h + fw * 2,20)).expandedTo(QApplication::globalStrut()); |
|
1086 } |
|
1087 |
|
1088 /*! \reimp |
|
1089 |
|
1090 */ |
|
1091 QSize Q3DateEdit::minimumSizeHint() const |
|
1092 { |
|
1093 return sizeHint(); |
|
1094 } |
|
1095 |
|
1096 |
|
1097 /*! |
|
1098 Returns the formatted number for section \a sec. This will |
|
1099 correspond to either the year, month or day section, depending on |
|
1100 the current display order. |
|
1101 |
|
1102 \sa setOrder() |
|
1103 */ |
|
1104 |
|
1105 QString Q3DateEdit::sectionFormattedText(int sec) |
|
1106 { |
|
1107 QString txt; |
|
1108 txt = sectionText(sec); |
|
1109 if (d->typing && sec == d->ed->focusSection()) |
|
1110 d->ed->setSectionSelection(sec, sectionOffsetEnd(sec) - txt.length(), |
|
1111 sectionOffsetEnd(sec)); |
|
1112 else |
|
1113 d->ed->setSectionSelection(sec, sectionOffsetEnd(sec) - sectionLength(sec), |
|
1114 sectionOffsetEnd(sec)); |
|
1115 txt = txt.rightJustified(sectionLength(sec), QDATETIMEEDIT_HIDDEN_CHAR); |
|
1116 return txt; |
|
1117 } |
|
1118 |
|
1119 |
|
1120 /*! |
|
1121 Returns the desired length (number of digits) of section \a sec. |
|
1122 This will correspond to either the year, month or day section, |
|
1123 depending on the current display order. |
|
1124 |
|
1125 \sa setOrder() |
|
1126 */ |
|
1127 |
|
1128 int Q3DateEdit::sectionLength(int sec) const |
|
1129 { |
|
1130 int val = 0; |
|
1131 if (sec == d->yearSection) { |
|
1132 val = 4; |
|
1133 } else if (sec == d->monthSection) { |
|
1134 val = 2; |
|
1135 } else if (sec == d->daySection) { |
|
1136 val = 2; |
|
1137 } |
|
1138 return val; |
|
1139 } |
|
1140 |
|
1141 /*! |
|
1142 Returns the text of section \a sec. This will correspond to either |
|
1143 the year, month or day section, depending on the current display |
|
1144 order. |
|
1145 |
|
1146 \sa setOrder() |
|
1147 */ |
|
1148 |
|
1149 QString Q3DateEdit::sectionText(int sec) const |
|
1150 { |
|
1151 int val = 0; |
|
1152 if (sec == d->yearSection) { |
|
1153 val = d->y; |
|
1154 } else if (sec == d->monthSection) { |
|
1155 val = d->m; |
|
1156 } else if (sec == d->daySection) { |
|
1157 val = d->d; |
|
1158 } |
|
1159 return QString::number(val); |
|
1160 } |
|
1161 |
|
1162 /*! \internal |
|
1163 |
|
1164 Returns the end of the section offset \a sec. |
|
1165 |
|
1166 */ |
|
1167 |
|
1168 int Q3DateEdit::sectionOffsetEnd(int sec) const |
|
1169 { |
|
1170 if (sec == d->yearSection) { |
|
1171 switch(d->ord) { |
|
1172 case DMY: |
|
1173 case MDY: |
|
1174 return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec); |
|
1175 case YMD: |
|
1176 case YDM: |
|
1177 return sectionLength(sec); |
|
1178 } |
|
1179 } else if (sec == d->monthSection) { |
|
1180 switch(d->ord) { |
|
1181 case DMY: |
|
1182 case YDM: |
|
1183 case YMD: |
|
1184 return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec); |
|
1185 case MDY: |
|
1186 return sectionLength(sec); |
|
1187 } |
|
1188 } else if (sec == d->daySection) { |
|
1189 switch(d->ord) { |
|
1190 case DMY: |
|
1191 return sectionLength(sec); |
|
1192 case YMD: |
|
1193 case MDY: |
|
1194 case YDM: |
|
1195 return sectionOffsetEnd(sec-1) + separator().length() + sectionLength(sec); |
|
1196 } |
|
1197 } |
|
1198 return 0; |
|
1199 } |
|
1200 |
|
1201 |
|
1202 /*! |
|
1203 \property Q3DateEdit::order |
|
1204 \brief the order in which the year, month and day appear |
|
1205 |
|
1206 The default order is locale dependent. |
|
1207 |
|
1208 \sa Order |
|
1209 */ |
|
1210 |
|
1211 void Q3DateEdit::setOrder(Q3DateEdit::Order order) |
|
1212 { |
|
1213 d->ord = order; |
|
1214 switch(d->ord) { |
|
1215 case DMY: |
|
1216 d->yearSection = 2; |
|
1217 d->monthSection = 1; |
|
1218 d->daySection = 0; |
|
1219 break; |
|
1220 case MDY: |
|
1221 d->yearSection = 2; |
|
1222 d->monthSection = 0; |
|
1223 d->daySection = 1; |
|
1224 break; |
|
1225 case YMD: |
|
1226 d->yearSection = 0; |
|
1227 d->monthSection = 1; |
|
1228 d->daySection = 2; |
|
1229 break; |
|
1230 case YDM: |
|
1231 d->yearSection = 0; |
|
1232 d->monthSection = 2; |
|
1233 d->daySection = 1; |
|
1234 break; |
|
1235 } |
|
1236 if (isVisible()) |
|
1237 d->ed->repaint(d->ed->rect()); |
|
1238 } |
|
1239 |
|
1240 |
|
1241 Q3DateEdit::Order Q3DateEdit::order() const |
|
1242 { |
|
1243 return d->ord; |
|
1244 } |
|
1245 |
|
1246 |
|
1247 /*! \internal |
|
1248 |
|
1249 */ |
|
1250 void Q3DateEdit::stepUp() |
|
1251 { |
|
1252 int sec = d->ed->focusSection(); |
|
1253 bool accepted = false; |
|
1254 if (sec == d->yearSection) { |
|
1255 if (!outOfRange(d->y+1, d->m, d->d)) { |
|
1256 accepted = true; |
|
1257 setYear(d->y+1); |
|
1258 } |
|
1259 } else if (sec == d->monthSection) { |
|
1260 if (!outOfRange(d->y, d->m+1, d->d)) { |
|
1261 accepted = true; |
|
1262 setMonth(d->m+1); |
|
1263 } |
|
1264 } else if (sec == d->daySection) { |
|
1265 if (!outOfRange(d->y, d->m, d->d+1)) { |
|
1266 accepted = true; |
|
1267 setDay(d->d+1); |
|
1268 } |
|
1269 } |
|
1270 if (accepted) { |
|
1271 d->changed = false; |
|
1272 emit valueChanged(date()); |
|
1273 } |
|
1274 d->ed->repaint(d->ed->rect()); |
|
1275 } |
|
1276 |
|
1277 |
|
1278 |
|
1279 /*! \internal |
|
1280 |
|
1281 */ |
|
1282 |
|
1283 void Q3DateEdit::stepDown() |
|
1284 { |
|
1285 int sec = d->ed->focusSection(); |
|
1286 bool accepted = false; |
|
1287 if (sec == d->yearSection) { |
|
1288 if (!outOfRange(d->y-1, d->m, d->d)) { |
|
1289 accepted = true; |
|
1290 setYear(d->y-1); |
|
1291 } |
|
1292 } else if (sec == d->monthSection) { |
|
1293 if (!outOfRange(d->y, d->m-1, d->d)) { |
|
1294 accepted = true; |
|
1295 setMonth(d->m-1); |
|
1296 } |
|
1297 } else if (sec == d->daySection) { |
|
1298 if (!outOfRange(d->y, d->m, d->d-1)) { |
|
1299 accepted = true; |
|
1300 setDay(d->d-1); |
|
1301 } |
|
1302 } |
|
1303 if (accepted) { |
|
1304 d->changed = false; |
|
1305 emit valueChanged(date()); |
|
1306 } |
|
1307 d->ed->repaint(d->ed->rect()); |
|
1308 } |
|
1309 |
|
1310 /*! |
|
1311 Sets the year to \a year, which must be a valid year. The range |
|
1312 currently supported is from 1752 to 8000. |
|
1313 |
|
1314 \sa QDate |
|
1315 */ |
|
1316 |
|
1317 void Q3DateEdit::setYear(int year) |
|
1318 { |
|
1319 if (year < 1752) |
|
1320 year = 1752; |
|
1321 if (year > 8000) |
|
1322 year = 8000; |
|
1323 if (!outOfRange(year, d->m, d->d)) { |
|
1324 d->y = year; |
|
1325 setMonth(d->m); |
|
1326 int tmp = d->dayCache; |
|
1327 setDay(d->dayCache); |
|
1328 d->dayCache = tmp; |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 |
|
1333 /*! |
|
1334 Sets the month to \a month, which must be a valid month, i.e. |
|
1335 between 1 and 12. |
|
1336 */ |
|
1337 |
|
1338 void Q3DateEdit::setMonth(int month) |
|
1339 { |
|
1340 if (month < 1) |
|
1341 month = 1; |
|
1342 if (month > 12) |
|
1343 month = 12; |
|
1344 if (!outOfRange(d->y, month, d->d)) { |
|
1345 d->m = month; |
|
1346 int tmp = d->dayCache; |
|
1347 setDay(d->dayCache); |
|
1348 d->dayCache = tmp; |
|
1349 } |
|
1350 } |
|
1351 |
|
1352 |
|
1353 /*! |
|
1354 Sets the day to \a day, which must be a valid day. The function |
|
1355 will ensure that the \a day set is valid for the month and year. |
|
1356 */ |
|
1357 |
|
1358 void Q3DateEdit::setDay(int day) |
|
1359 { |
|
1360 if (day < 1) |
|
1361 day = 1; |
|
1362 if (day > 31) |
|
1363 day = 31; |
|
1364 if (d->m > 0 && d->y > 1752) { |
|
1365 while (!QDate::isValid(d->y, d->m, day)) |
|
1366 --day; |
|
1367 if (!outOfRange(d->y, d->m, day)) |
|
1368 d->d = day; |
|
1369 } else if (d->m > 0) { |
|
1370 if (day > 0 && day < 32) { |
|
1371 if (!outOfRange(d->y, d->m, day)) |
|
1372 d->d = day; |
|
1373 } |
|
1374 } |
|
1375 d->dayCache = d->d; |
|
1376 } |
|
1377 |
|
1378 |
|
1379 /*! |
|
1380 \property Q3DateEdit::date |
|
1381 \brief the editor's date value. |
|
1382 |
|
1383 If the date property is not valid, the editor displays all zeroes |
|
1384 and Q3DateEdit::date() will return an invalid date. It is strongly |
|
1385 recommended that the editor is given a default date value (e.g. |
|
1386 currentDate()). That way, attempts to set the date property to an |
|
1387 invalid date will fail. |
|
1388 |
|
1389 When changing the date property, if the date is less than |
|
1390 minValue(), or is greater than maxValue(), nothing happens. |
|
1391 */ |
|
1392 |
|
1393 void Q3DateEdit::setDate(const QDate& date) |
|
1394 { |
|
1395 if (!date.isValid()) { |
|
1396 d->y = 0; |
|
1397 d->m = 0; |
|
1398 d->d = 0; |
|
1399 d->dayCache = 0; |
|
1400 } else { |
|
1401 if (date > maxValue() || date < minValue()) |
|
1402 return; |
|
1403 d->y = date.year(); |
|
1404 d->m = date.month(); |
|
1405 d->d = date.day(); |
|
1406 d->dayCache = d->d; |
|
1407 emit valueChanged(date); |
|
1408 } |
|
1409 d->changed = false; |
|
1410 d->ed->repaint(d->ed->rect()); |
|
1411 } |
|
1412 |
|
1413 QDate Q3DateEdit::date() const |
|
1414 { |
|
1415 if (QDate::isValid(d->y, d->m, d->d)) |
|
1416 return QDate(d->y, d->m, d->d); |
|
1417 return QDate(); |
|
1418 } |
|
1419 |
|
1420 /*! \internal |
|
1421 |
|
1422 Returns true if \a y, \a m, \a d is out of range, otherwise returns |
|
1423 false. |
|
1424 |
|
1425 \sa setRange() |
|
1426 |
|
1427 */ |
|
1428 |
|
1429 bool Q3DateEdit::outOfRange(int y, int m, int d) const |
|
1430 { |
|
1431 if (QDate::isValid(y, m, d)) { |
|
1432 QDate currentDate(y, m, d); |
|
1433 if (currentDate > maxValue() || |
|
1434 currentDate < minValue()) { |
|
1435 //## outOfRange should set overwrite? |
|
1436 return true; |
|
1437 } |
|
1438 return false; |
|
1439 } |
|
1440 return false; /* assume ok */ |
|
1441 } |
|
1442 |
|
1443 /*! \internal |
|
1444 |
|
1445 */ |
|
1446 |
|
1447 void Q3DateEdit::addNumber(int sec, int num) |
|
1448 { |
|
1449 if (sec == -1) |
|
1450 return; |
|
1451 if (d->timerId) |
|
1452 killTimer(d->timerId); |
|
1453 d->timerId = 0; |
|
1454 bool overwrite = false; |
|
1455 bool accepted = false; |
|
1456 d->typing = true; |
|
1457 QString txt; |
|
1458 if (sec == d->yearSection) { |
|
1459 txt = QString::number(d->y); |
|
1460 if (d->overwrite || txt.length() == 4) { |
|
1461 accepted = true; |
|
1462 d->y = num; |
|
1463 } else { |
|
1464 txt += QString::number(num); |
|
1465 if (txt.length() == 4 ) { |
|
1466 const int val = qBound(1792, txt.toInt(), 8000); |
|
1467 if (outOfRange(val, d->m, d->d)) { |
|
1468 txt = QString::number(d->y); |
|
1469 } else { |
|
1470 accepted = true; |
|
1471 d->y = val; |
|
1472 } |
|
1473 } else { |
|
1474 accepted = true; |
|
1475 d->y = txt.toInt(); |
|
1476 } |
|
1477 if (d->adv && txt.length() == 4) { |
|
1478 d->ed->setFocusSection(d->ed->focusSection()+1); |
|
1479 overwrite = true; |
|
1480 } |
|
1481 } |
|
1482 } else if (sec == d->monthSection) { |
|
1483 txt = QString::number(d->m); |
|
1484 if (d->overwrite || txt.length() == 2) { |
|
1485 accepted = true; |
|
1486 d->m = num; |
|
1487 } else { |
|
1488 txt += QString::number(num); |
|
1489 int temp = txt.toInt(); |
|
1490 if (temp > 12) |
|
1491 temp = num; |
|
1492 if (outOfRange(d->y, temp, d->d)) |
|
1493 txt = QString::number(d->m); |
|
1494 else { |
|
1495 accepted = true; |
|
1496 d->m = temp; |
|
1497 } |
|
1498 if (d->adv && txt.length() == 2) { |
|
1499 d->ed->setFocusSection(d->ed->focusSection()+1); |
|
1500 overwrite = true; |
|
1501 } |
|
1502 } |
|
1503 } else if (sec == d->daySection) { |
|
1504 txt = QString::number(d->d); |
|
1505 if (d->overwrite || txt.length() == 2) { |
|
1506 accepted = true; |
|
1507 d->d = num; |
|
1508 d->dayCache = d->d; |
|
1509 } else { |
|
1510 txt += QString::number(num); |
|
1511 int temp = txt.toInt(); |
|
1512 if (temp > 31) |
|
1513 temp = num; |
|
1514 if (outOfRange(d->y, d->m, temp)) |
|
1515 txt = QString::number(d->d); |
|
1516 else { |
|
1517 accepted = true; |
|
1518 d->d = temp; |
|
1519 d->dayCache = d->d; |
|
1520 } |
|
1521 if (d->adv && txt.length() == 2) { |
|
1522 d->ed->setFocusSection(d->ed->focusSection()+1); |
|
1523 overwrite = true; |
|
1524 } |
|
1525 } |
|
1526 } |
|
1527 if (accepted) { |
|
1528 d->changed = false; |
|
1529 emit valueChanged(date()); |
|
1530 } |
|
1531 d->overwrite = overwrite; |
|
1532 d->timerId = startTimer(qApp->doubleClickInterval()*4); |
|
1533 d->ed->repaint(d->ed->rect()); |
|
1534 } |
|
1535 |
|
1536 |
|
1537 /*! \internal |
|
1538 |
|
1539 */ |
|
1540 |
|
1541 bool Q3DateEdit::setFocusSection(int s) |
|
1542 { |
|
1543 if (s != d->ed->focusSection()) { |
|
1544 if (d->timerId) |
|
1545 killTimer(d->timerId); |
|
1546 d->timerId = 0; |
|
1547 d->overwrite = true; |
|
1548 d->typing = false; |
|
1549 fix(); // will emit valueChanged if necessary |
|
1550 } |
|
1551 return d->ed->setFocusSection(s); |
|
1552 } |
|
1553 |
|
1554 |
|
1555 /*! |
|
1556 Attempts to fix any invalid date entries. |
|
1557 |
|
1558 The rules applied are as follows: |
|
1559 |
|
1560 \list |
|
1561 \i If the year has four digits it is left unchanged. |
|
1562 \i If the year has two digits, the year will be changed to four |
|
1563 digits in the range current year - 70 to current year + 29. |
|
1564 \i If the year has three digits in the range 100..999, the |
|
1565 current millennium, i.e. 2000, will be added giving a year |
|
1566 in the range 2100..2999. |
|
1567 \i If the day or month is 0 then it will be set to 1 or the |
|
1568 minimum valid day/month in the range. |
|
1569 \endlist |
|
1570 */ |
|
1571 |
|
1572 void Q3DateEdit::fix() |
|
1573 { |
|
1574 bool changed = false; |
|
1575 int currentYear = QDate::currentDate().year(); |
|
1576 int year = d->y; |
|
1577 if (year < 100) { |
|
1578 int currentCentury = currentYear / 100; |
|
1579 year += currentCentury * 100; |
|
1580 if (currentYear > year) { |
|
1581 if (currentYear > year + 70) |
|
1582 year += 100; |
|
1583 } else { |
|
1584 if (year >= currentYear + 30) |
|
1585 year -= 100; |
|
1586 } |
|
1587 changed = true; |
|
1588 } else if (year < 1000) { |
|
1589 int currentMillennium = currentYear / 10; |
|
1590 year += currentMillennium * 10; |
|
1591 changed = true; |
|
1592 } else if (d->d == 0) { |
|
1593 d->d = 1; |
|
1594 changed = true; |
|
1595 } else if (d->m == 0) { |
|
1596 d->m = 1; |
|
1597 changed = true; |
|
1598 } |
|
1599 if (outOfRange(year, d->m, d->d)) { |
|
1600 if (minValue().isValid() && date() < minValue()) { |
|
1601 d->d = minValue().day(); |
|
1602 d->dayCache = d->d; |
|
1603 d->m = minValue().month(); |
|
1604 d->y = minValue().year(); |
|
1605 } |
|
1606 if (date() > maxValue()) { |
|
1607 d->d = maxValue().day(); |
|
1608 d->dayCache = d->d; |
|
1609 d->m = maxValue().month(); |
|
1610 d->y = maxValue().year(); |
|
1611 } |
|
1612 changed = true; |
|
1613 } else if (changed) |
|
1614 setYear(year); |
|
1615 if (changed) { |
|
1616 emit valueChanged(date()); |
|
1617 d->changed = false; |
|
1618 } |
|
1619 } |
|
1620 |
|
1621 |
|
1622 /*! \reimp |
|
1623 |
|
1624 */ |
|
1625 |
|
1626 bool Q3DateEdit::event(QEvent *e) |
|
1627 { |
|
1628 if(e->type() == QEvent::FocusOut) { |
|
1629 d->typing = false; |
|
1630 fix(); |
|
1631 // the following can't be done in fix() because fix() called |
|
1632 // from all over the place and it will break the old behaviour |
|
1633 if (!QDate::isValid(d->y, d->m, d->d)) { |
|
1634 d->dayCache = d->d; |
|
1635 int i = d->d; |
|
1636 for (; i > 0; i--) { |
|
1637 d->d = i; |
|
1638 if (QDate::isValid(d->y, d->m, d->d)) |
|
1639 break; |
|
1640 } |
|
1641 d->changed = true; |
|
1642 } |
|
1643 if (d->changed) { |
|
1644 emit valueChanged(date()); |
|
1645 d->changed = false; |
|
1646 } |
|
1647 } else if (e->type() == QEvent::LocaleChange) { |
|
1648 readLocaleSettings(); |
|
1649 d->ed->setSeparator(localDateSep()); |
|
1650 setOrder(localOrder()); |
|
1651 } |
|
1652 return Q3DateTimeEditBase::event(e); |
|
1653 } |
|
1654 |
|
1655 /*! |
|
1656 \internal |
|
1657 |
|
1658 Function which is called whenever the user tries to |
|
1659 remove the first number from \a sec by pressing the backspace key. |
|
1660 */ |
|
1661 |
|
1662 void Q3DateEdit::removeFirstNumber(int sec) |
|
1663 { |
|
1664 if (sec == -1) |
|
1665 return; |
|
1666 QString txt; |
|
1667 if (sec == d->yearSection) { |
|
1668 txt = QString::number(d->y); |
|
1669 txt = txt.mid(1, txt.length()) + QLatin1Char('0'); |
|
1670 d->y = txt.toInt(); |
|
1671 } else if (sec == d->monthSection) { |
|
1672 txt = QString::number(d->m); |
|
1673 txt = txt.mid(1, txt.length()) + QLatin1Char('0'); |
|
1674 d->m = txt.toInt(); |
|
1675 } else if (sec == d->daySection) { |
|
1676 txt = QString::number(d->d); |
|
1677 txt = txt.mid(1, txt.length()) + QLatin1Char('0'); |
|
1678 d->d = txt.toInt(); |
|
1679 d->dayCache = d->d; |
|
1680 } |
|
1681 d->ed->repaint(d->ed->rect()); |
|
1682 } |
|
1683 |
|
1684 /*! \internal |
|
1685 |
|
1686 */ |
|
1687 |
|
1688 void Q3DateEdit::removeLastNumber(int sec) |
|
1689 { |
|
1690 if (sec == -1) |
|
1691 return; |
|
1692 QString txt; |
|
1693 if (sec == d->yearSection) { |
|
1694 txt = QString::number(d->y); |
|
1695 txt = txt.mid(0, txt.length()-1); |
|
1696 d->y = txt.toInt(); |
|
1697 } else if (sec == d->monthSection) { |
|
1698 txt = QString::number(d->m); |
|
1699 txt = txt.mid(0, txt.length()-1); |
|
1700 d->m = txt.toInt(); |
|
1701 } else if (sec == d->daySection) { |
|
1702 txt = QString::number(d->d); |
|
1703 txt = txt.mid(0, txt.length()-1); |
|
1704 d->d = txt.toInt(); |
|
1705 d->dayCache = d->d; |
|
1706 } |
|
1707 d->ed->repaint(d->ed->rect()); |
|
1708 } |
|
1709 |
|
1710 /*! |
|
1711 \property Q3DateEdit::autoAdvance |
|
1712 \brief whether the editor automatically advances to the next |
|
1713 section |
|
1714 |
|
1715 If autoAdvance is true, the editor will automatically advance |
|
1716 focus to the next date section if a user has completed a section. |
|
1717 The default is false. |
|
1718 */ |
|
1719 |
|
1720 void Q3DateEdit::setAutoAdvance(bool advance) |
|
1721 { |
|
1722 d->adv = advance; |
|
1723 } |
|
1724 |
|
1725 |
|
1726 bool Q3DateEdit::autoAdvance() const |
|
1727 { |
|
1728 return d->adv; |
|
1729 } |
|
1730 |
|
1731 /*! \reimp |
|
1732 */ |
|
1733 |
|
1734 void Q3DateEdit::timerEvent(QTimerEvent *) |
|
1735 { |
|
1736 d->overwrite = true; |
|
1737 } |
|
1738 |
|
1739 /*! |
|
1740 \fn void Q3DateEdit::valueChanged(const QDate& date) |
|
1741 |
|
1742 This signal is emitted whenever the editor's value changes. The \a |
|
1743 date parameter is the new value. |
|
1744 */ |
|
1745 |
|
1746 /////////// |
|
1747 |
|
1748 class Q3TimeEditPrivate |
|
1749 { |
|
1750 public: |
|
1751 int h; |
|
1752 int m; |
|
1753 int s; |
|
1754 uint display; |
|
1755 bool adv; |
|
1756 bool overwrite; |
|
1757 int timerId; |
|
1758 bool typing; |
|
1759 QTime min; |
|
1760 QTime max; |
|
1761 bool changed; |
|
1762 Q3DateTimeEditor *ed; |
|
1763 Q3SpinWidget *controls; |
|
1764 }; |
|
1765 |
|
1766 /*! |
|
1767 \class Q3TimeEdit |
|
1768 \brief The Q3TimeEdit class provides a time editor. |
|
1769 |
|
1770 \compat |
|
1771 |
|
1772 Q3TimeEdit allows the user to edit times by using the keyboard or |
|
1773 the arrow keys to increase/decrease time values. The arrow keys |
|
1774 can be used to move from section to section within the Q3TimeEdit |
|
1775 box. The user can automatically be moved to the next section once |
|
1776 they complete a section using setAutoAdvance(). Times appear in |
|
1777 hour, minute, second order. It is recommended that the Q3TimeEdit |
|
1778 is initialised with a time, e.g. |
|
1779 \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 1 |
|
1780 Here we've created a Q3TimeEdit widget set to the current time. |
|
1781 We've also set the minimum value to the current time and the |
|
1782 maximum time to one hour from now. |
|
1783 |
|
1784 The maximum and minimum values for a time value in the time editor |
|
1785 default to the maximum and minimum values for a QTime. You can |
|
1786 change this by calling setMinValue(), setMaxValue() or setRange(). |
|
1787 |
|
1788 Terminology: A QTimeWidget consists of three sections, one each |
|
1789 for the hour, minute and second. You can change the separator |
|
1790 character using setSeparator(), by default the separator is read |
|
1791 from the system's settings. |
|
1792 |
|
1793 \img datetimewidgets.png Date Time Widgets |
|
1794 |
|
1795 \sa QTime Q3DateEdit Q3DateTimeEdit |
|
1796 */ |
|
1797 |
|
1798 |
|
1799 /*! |
|
1800 Constructs an empty time edit with parent \a parent and called \a |
|
1801 name. |
|
1802 */ |
|
1803 |
|
1804 Q3TimeEdit::Q3TimeEdit(QWidget * parent, const char * name) |
|
1805 : Q3DateTimeEditBase(parent, name) |
|
1806 { |
|
1807 init(); |
|
1808 } |
|
1809 |
|
1810 /*! |
|
1811 \overload |
|
1812 |
|
1813 Constructs a time edit with the initial time value, \a time, |
|
1814 parent \a parent and called \a name. |
|
1815 */ |
|
1816 |
|
1817 Q3TimeEdit::Q3TimeEdit(const QTime& time, QWidget * parent, const char * name) |
|
1818 : Q3DateTimeEditBase(parent, name) |
|
1819 { |
|
1820 init(); |
|
1821 setTime(time); |
|
1822 } |
|
1823 |
|
1824 /*! \internal |
|
1825 */ |
|
1826 |
|
1827 void Q3TimeEdit::init() |
|
1828 { |
|
1829 d = new Q3TimeEditPrivate(); |
|
1830 d->controls = new QDateTimeSpinWidget(this, 0); |
|
1831 d->ed = new Q3DateTimeEditor(this, d->controls, "time edit base"); |
|
1832 d->controls->setEditWidget(d->ed); |
|
1833 setFocusProxy(d->ed); |
|
1834 connect(d->controls, SIGNAL(stepUpPressed()), SLOT(stepUp())); |
|
1835 connect(d->controls, SIGNAL(stepDownPressed()), SLOT(stepDown())); |
|
1836 |
|
1837 d->ed->appendSection(QNumberSection(0,0, true, 0)); |
|
1838 d->ed->appendSection(QNumberSection(0,0, true, 1)); |
|
1839 d->ed->appendSection(QNumberSection(0,0, true, 2)); |
|
1840 d->ed->setSeparator(localTimeSep()); |
|
1841 |
|
1842 d->h = 0; |
|
1843 d->m = 0; |
|
1844 d->s = 0; |
|
1845 d->display = Hours | Minutes | Seconds; |
|
1846 if (lAMPM) { |
|
1847 d->display |= AMPM; |
|
1848 d->ed->appendSection(QNumberSection(0,0, false, 3)); |
|
1849 } |
|
1850 d->adv = false; |
|
1851 d->overwrite = true; |
|
1852 d->timerId = 0; |
|
1853 d->typing = false; |
|
1854 d->min = QTime(0, 0, 0); |
|
1855 d->max = QTime(23, 59, 59); |
|
1856 d->changed = false; |
|
1857 |
|
1858 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); |
|
1859 |
|
1860 refcount++; |
|
1861 } |
|
1862 |
|
1863 /*! |
|
1864 Destroys the object and frees any allocated resources. |
|
1865 */ |
|
1866 |
|
1867 Q3TimeEdit::~Q3TimeEdit() |
|
1868 { |
|
1869 delete d; |
|
1870 if (!--refcount) |
|
1871 cleanup(); |
|
1872 } |
|
1873 |
|
1874 /*! |
|
1875 \property Q3TimeEdit::minValue |
|
1876 \brief the minimum time value |
|
1877 |
|
1878 Setting the minimum time value is equivalent to calling |
|
1879 Q3TimeEdit::setRange(\e t, maxValue()), where \e t is the minimum |
|
1880 time. The default minimum time is 00:00:00. |
|
1881 |
|
1882 \sa maxValue setRange() |
|
1883 */ |
|
1884 |
|
1885 QTime Q3TimeEdit::minValue() const |
|
1886 { |
|
1887 return d->min; |
|
1888 } |
|
1889 |
|
1890 /*! |
|
1891 \property Q3TimeEdit::maxValue |
|
1892 \brief the maximum time value |
|
1893 |
|
1894 Setting the maximum time value is equivalent to calling |
|
1895 Q3TimeEdit::setRange(minValue(), \e t), where \e t is the maximum |
|
1896 time. The default maximum time is 23:59:59. |
|
1897 |
|
1898 \sa minValue setRange() |
|
1899 */ |
|
1900 |
|
1901 QTime Q3TimeEdit::maxValue() const |
|
1902 { |
|
1903 return d->max; |
|
1904 } |
|
1905 |
|
1906 |
|
1907 /*! |
|
1908 Sets the valid input range for the editor to be from \a min to \a |
|
1909 max inclusive. If \a min is invalid no minimum time is set. |
|
1910 Similarly, if \a max is invalid no maximum time is set. |
|
1911 */ |
|
1912 |
|
1913 void Q3TimeEdit::setRange(const QTime& min, const QTime& max) |
|
1914 { |
|
1915 if (min.isValid()) |
|
1916 d->min = min; |
|
1917 if (max.isValid()) |
|
1918 d->max = max; |
|
1919 } |
|
1920 |
|
1921 /*! |
|
1922 \property Q3TimeEdit::display |
|
1923 \brief the sections that are displayed in the time edit |
|
1924 |
|
1925 The value can be any combination of the values in the Display enum. |
|
1926 By default, the widget displays hours, minutes and seconds. |
|
1927 */ |
|
1928 void Q3TimeEdit::setDisplay(uint display) |
|
1929 { |
|
1930 if (d->display == display) |
|
1931 return; |
|
1932 |
|
1933 d->ed->clearSections(); |
|
1934 d->display = display; |
|
1935 if (d->display & Hours) |
|
1936 d->ed->appendSection(QNumberSection(0,0, true, 0)); |
|
1937 if (d->display & Minutes) |
|
1938 d->ed->appendSection(QNumberSection(0,0, true, 1)); |
|
1939 if (d->display & Seconds) |
|
1940 d->ed->appendSection(QNumberSection(0,0, true, 2)); |
|
1941 if (d->display & AMPM) |
|
1942 d->ed->appendSection(QNumberSection(0,0, false, 3)); |
|
1943 |
|
1944 d->ed->setFocusSection(0); |
|
1945 d->ed->update(); |
|
1946 } |
|
1947 |
|
1948 uint Q3TimeEdit::display() const |
|
1949 { |
|
1950 return d->display; |
|
1951 } |
|
1952 |
|
1953 /*! |
|
1954 \property Q3TimeEdit::time |
|
1955 \brief the editor's time value. |
|
1956 |
|
1957 When changing the time property, if the time is less than |
|
1958 minValue(), or is greater than maxValue(), nothing happens. |
|
1959 */ |
|
1960 |
|
1961 void Q3TimeEdit::setTime(const QTime& time) |
|
1962 { |
|
1963 if (!time.isValid()) { |
|
1964 d->h = 0; |
|
1965 d->m = 0; |
|
1966 d->s = 0; |
|
1967 } else { |
|
1968 if (time > maxValue() || time < minValue()) |
|
1969 return; |
|
1970 d->h = time.hour(); |
|
1971 d->m = time.minute(); |
|
1972 d->s = time.second(); |
|
1973 emit valueChanged(time); |
|
1974 } |
|
1975 d->changed = false; |
|
1976 d->ed->repaint(d->ed->rect()); |
|
1977 } |
|
1978 |
|
1979 QTime Q3TimeEdit::time() const |
|
1980 { |
|
1981 if (QTime::isValid(d->h, d->m, d->s)) |
|
1982 return QTime(d->h, d->m, d->s); |
|
1983 return QTime(); |
|
1984 } |
|
1985 |
|
1986 /*! |
|
1987 \property Q3TimeEdit::autoAdvance |
|
1988 \brief whether the editor automatically advances to the next |
|
1989 section |
|
1990 |
|
1991 If autoAdvance is true, the editor will automatically advance |
|
1992 focus to the next time section if a user has completed a section. |
|
1993 The default is false. |
|
1994 */ |
|
1995 |
|
1996 void Q3TimeEdit::setAutoAdvance(bool advance) |
|
1997 { |
|
1998 d->adv = advance; |
|
1999 } |
|
2000 |
|
2001 bool Q3TimeEdit::autoAdvance() const |
|
2002 { |
|
2003 return d->adv; |
|
2004 } |
|
2005 |
|
2006 /*! |
|
2007 Sets the separator to \a s. Note that currently only the first |
|
2008 character of \a s is used. |
|
2009 */ |
|
2010 |
|
2011 void Q3TimeEdit::setSeparator(const QString& s) |
|
2012 { |
|
2013 d->ed->setSeparator(s); |
|
2014 } |
|
2015 |
|
2016 /*! |
|
2017 Returns the editor's separator. |
|
2018 */ |
|
2019 |
|
2020 QString Q3TimeEdit::separator() const |
|
2021 { |
|
2022 return d->ed->separator(); |
|
2023 } |
|
2024 |
|
2025 |
|
2026 /*! |
|
2027 \fn void Q3TimeEdit::valueChanged(const QTime& time) |
|
2028 |
|
2029 This signal is emitted whenever the editor's value changes. The \a |
|
2030 time parameter is the new value. |
|
2031 */ |
|
2032 |
|
2033 /*! \reimp |
|
2034 |
|
2035 */ |
|
2036 |
|
2037 bool Q3TimeEdit::event(QEvent *e) |
|
2038 { |
|
2039 if (e->type() == QEvent::FocusOut) { |
|
2040 d->typing = false; |
|
2041 if (d->changed) { |
|
2042 emit valueChanged(time()); |
|
2043 d->changed = false; |
|
2044 } |
|
2045 } else if (e->type() == QEvent::LocaleChange) { |
|
2046 readLocaleSettings(); |
|
2047 d->ed->setSeparator(localTimeSep()); |
|
2048 } |
|
2049 return Q3DateTimeEditBase::event(e); |
|
2050 } |
|
2051 |
|
2052 /*! \reimp |
|
2053 |
|
2054 */ |
|
2055 |
|
2056 void Q3TimeEdit::timerEvent(QTimerEvent *) |
|
2057 { |
|
2058 d->overwrite = true; |
|
2059 } |
|
2060 |
|
2061 |
|
2062 /*! \internal |
|
2063 |
|
2064 */ |
|
2065 |
|
2066 void Q3TimeEdit::stepUp() |
|
2067 { |
|
2068 int sec = d->ed->mapSection(d->ed->focusSection()); |
|
2069 bool accepted = true; |
|
2070 switch(sec) { |
|
2071 case 0: |
|
2072 if (!outOfRange(d->h+1, d->m, d->s)) |
|
2073 setHour(d->h+1); |
|
2074 else |
|
2075 setHour(d->min.hour()); |
|
2076 break; |
|
2077 case 1: |
|
2078 if (!outOfRange(d->h, d->m+1, d->s)) |
|
2079 setMinute(d->m+1); |
|
2080 else |
|
2081 setMinute(d->min.minute()); |
|
2082 break; |
|
2083 case 2: |
|
2084 if (!outOfRange(d->h, d->m, d->s+1)) |
|
2085 setSecond(d->s+1); |
|
2086 else |
|
2087 setSecond(d->min.second()); |
|
2088 break; |
|
2089 case 3: |
|
2090 if (d->h < 12) |
|
2091 setHour(d->h+12); |
|
2092 else |
|
2093 setHour(d->h-12); |
|
2094 break; |
|
2095 default: |
|
2096 accepted = false; |
|
2097 qWarning("Q3TimeEdit::stepUp: Focus section out of range!"); |
|
2098 break; |
|
2099 } |
|
2100 if (accepted) { |
|
2101 d->changed = false; |
|
2102 emit valueChanged(time()); |
|
2103 } |
|
2104 d->ed->repaint(d->ed->rect()); |
|
2105 } |
|
2106 |
|
2107 |
|
2108 /*! \internal |
|
2109 |
|
2110 */ |
|
2111 |
|
2112 void Q3TimeEdit::stepDown() |
|
2113 { |
|
2114 int sec = d->ed->mapSection(d->ed->focusSection()); |
|
2115 |
|
2116 bool accepted = true; |
|
2117 switch(sec) { |
|
2118 case 0: |
|
2119 if (!outOfRange(d->h-1, d->m, d->s)) |
|
2120 setHour(d->h-1); |
|
2121 else |
|
2122 setHour(d->max.hour()); |
|
2123 break; |
|
2124 case 1: |
|
2125 if (!outOfRange(d->h, d->m-1, d->s)) |
|
2126 setMinute(d->m-1); |
|
2127 else |
|
2128 setMinute(d->max.minute()); |
|
2129 break; |
|
2130 case 2: |
|
2131 if (!outOfRange(d->h, d->m, d->s-1)) |
|
2132 setSecond(d->s-1); |
|
2133 else |
|
2134 setSecond(d->max.second()); |
|
2135 break; |
|
2136 case 3: |
|
2137 if (d->h > 11) |
|
2138 setHour(d->h-12); |
|
2139 else |
|
2140 setHour(d->h+12); |
|
2141 break; |
|
2142 default: |
|
2143 accepted = false; |
|
2144 qWarning("Q3TimeEdit::stepDown: Focus section out of range!"); |
|
2145 break; |
|
2146 } |
|
2147 if (accepted) { |
|
2148 d->changed = false; |
|
2149 emit valueChanged(time()); |
|
2150 } |
|
2151 d->ed->repaint(d->ed->rect()); |
|
2152 } |
|
2153 |
|
2154 |
|
2155 /*! |
|
2156 Returns the formatted number for section \a sec. This will |
|
2157 correspond to either the hour, minute or second section, depending |
|
2158 on \a sec. |
|
2159 */ |
|
2160 |
|
2161 QString Q3TimeEdit::sectionFormattedText(int sec) |
|
2162 { |
|
2163 QString txt; |
|
2164 txt = sectionText(sec); |
|
2165 txt = txt.rightJustified(2, QDATETIMEEDIT_HIDDEN_CHAR); |
|
2166 int offset = sec*2+sec*separator().length() + txt.length(); |
|
2167 if (d->typing && sec == d->ed->focusSection()) |
|
2168 d->ed->setSectionSelection(sec, offset - txt.length(), offset); |
|
2169 else |
|
2170 d->ed->setSectionSelection(sec, offset - txt.length(), offset); |
|
2171 |
|
2172 return txt; |
|
2173 } |
|
2174 |
|
2175 |
|
2176 /*! \internal |
|
2177 |
|
2178 */ |
|
2179 |
|
2180 bool Q3TimeEdit::setFocusSection(int sec) |
|
2181 { |
|
2182 if (sec != d->ed->focusSection()) { |
|
2183 if (d->timerId) |
|
2184 killTimer(d->timerId); |
|
2185 d->timerId = 0; |
|
2186 d->overwrite = true; |
|
2187 d->typing = false; |
|
2188 QString txt = sectionText(sec); |
|
2189 txt = txt.rightJustified(2, QDATETIMEEDIT_HIDDEN_CHAR); |
|
2190 int offset = sec*2+sec*separator().length() + txt.length(); |
|
2191 d->ed->setSectionSelection(sec, offset - txt.length(), offset); |
|
2192 if (d->changed) { |
|
2193 emit valueChanged(time()); |
|
2194 d->changed = false; |
|
2195 } |
|
2196 } |
|
2197 return d->ed->setFocusSection(sec); |
|
2198 } |
|
2199 |
|
2200 |
|
2201 /*! |
|
2202 Sets the hour to \a h, which must be a valid hour, i.e. in the |
|
2203 range 0..24. |
|
2204 */ |
|
2205 |
|
2206 void Q3TimeEdit::setHour(int h) |
|
2207 { |
|
2208 if (h < 0) |
|
2209 h = 0; |
|
2210 if (h > 23) |
|
2211 h = 23; |
|
2212 d->h = h; |
|
2213 } |
|
2214 |
|
2215 |
|
2216 /*! |
|
2217 Sets the minute to \a m, which must be a valid minute, i.e. in the |
|
2218 range 0..59. |
|
2219 */ |
|
2220 |
|
2221 void Q3TimeEdit::setMinute(int m) |
|
2222 { |
|
2223 if (m < 0) |
|
2224 m = 0; |
|
2225 if (m > 59) |
|
2226 m = 59; |
|
2227 d->m = m; |
|
2228 } |
|
2229 |
|
2230 |
|
2231 /*! |
|
2232 Sets the second to \a s, which must be a valid second, i.e. in the |
|
2233 range 0..59. |
|
2234 */ |
|
2235 |
|
2236 void Q3TimeEdit::setSecond(int s) |
|
2237 { |
|
2238 if (s < 0) |
|
2239 s = 0; |
|
2240 if (s > 59) |
|
2241 s = 59; |
|
2242 d->s = s; |
|
2243 } |
|
2244 |
|
2245 |
|
2246 /*! \internal |
|
2247 |
|
2248 Returns the text of section \a sec. |
|
2249 |
|
2250 */ |
|
2251 |
|
2252 QString Q3TimeEdit::sectionText(int sec) |
|
2253 { |
|
2254 sec = d->ed->mapSection(sec); |
|
2255 |
|
2256 QString txt; |
|
2257 switch(sec) { |
|
2258 case 0: |
|
2259 if (!(d->display & AMPM) || (d->h < 13 && d->h)) { // I wished the day stared at 0:00 for everybody |
|
2260 txt = QString::number(d->h); |
|
2261 } else { |
|
2262 if (d->h) |
|
2263 txt = QString::number(d->h - 12); |
|
2264 else |
|
2265 txt = QLatin1String("12"); |
|
2266 } |
|
2267 break; |
|
2268 case 1: |
|
2269 txt = QString::number(d->m); |
|
2270 break; |
|
2271 case 2: |
|
2272 txt = QString::number(d->s); |
|
2273 break; |
|
2274 case 3: |
|
2275 if (d->h < 12) { |
|
2276 if (lAM) |
|
2277 txt = *lAM; |
|
2278 else |
|
2279 txt = QString::fromLatin1("AM"); |
|
2280 } else { |
|
2281 if (lPM) |
|
2282 txt = *lPM; |
|
2283 else |
|
2284 txt = QString::fromLatin1("PM"); |
|
2285 } |
|
2286 break; |
|
2287 default: |
|
2288 break; |
|
2289 } |
|
2290 return txt; |
|
2291 } |
|
2292 |
|
2293 |
|
2294 /*! \internal |
|
2295 Returns true if \a h, \a m, and \a s are out of range. |
|
2296 */ |
|
2297 |
|
2298 bool Q3TimeEdit::outOfRange(int h, int m, int s) const |
|
2299 { |
|
2300 if (QTime::isValid(h, m, s)) { |
|
2301 QTime currentTime(h, m, s); |
|
2302 if (currentTime > maxValue() || |
|
2303 currentTime < minValue()) |
|
2304 return true; |
|
2305 else |
|
2306 return false; |
|
2307 } |
|
2308 return true; |
|
2309 } |
|
2310 |
|
2311 /*! \internal |
|
2312 |
|
2313 */ |
|
2314 |
|
2315 void Q3TimeEdit::addNumber(int sec, int num) |
|
2316 { |
|
2317 if (sec == -1) |
|
2318 return; |
|
2319 sec = d->ed->mapSection(sec); |
|
2320 if (d->timerId) |
|
2321 killTimer(d->timerId); |
|
2322 d->timerId = 0; |
|
2323 bool overwrite = false; |
|
2324 bool accepted = false; |
|
2325 d->typing = true; |
|
2326 QString txt; |
|
2327 |
|
2328 switch(sec) { |
|
2329 case 0: |
|
2330 txt = (d->display & AMPM && d->h > 12) ? |
|
2331 QString::number(d->h - 12) : QString::number(d->h); |
|
2332 |
|
2333 if (d->overwrite || txt.length() == 2) { |
|
2334 if (d->display & AMPM && num == 0) |
|
2335 break; // Don't process 0 in 12 hour clock mode |
|
2336 if (d->display & AMPM && d->h > 11) |
|
2337 num += 12; |
|
2338 if (!outOfRange(num, d->m, d->s)) { |
|
2339 accepted = true; |
|
2340 d->h = num; |
|
2341 } |
|
2342 } else { |
|
2343 txt += QString::number(num); |
|
2344 int temp = txt.toInt(); |
|
2345 |
|
2346 if (d->display & AMPM) { |
|
2347 if (temp == 12) { |
|
2348 if (d->h < 12) { |
|
2349 temp = 0; |
|
2350 } |
|
2351 accepted = true; |
|
2352 } else if (outOfRange(temp + 12, d->m, d->s)) { |
|
2353 txt = QString::number(d->h); |
|
2354 } else { |
|
2355 if (d->h > 11) { |
|
2356 temp += 12; |
|
2357 } |
|
2358 accepted = true; |
|
2359 } |
|
2360 } else if (!(d->display & AMPM) && outOfRange(temp, d->m, d->s)) { |
|
2361 txt = QString::number(d->h); |
|
2362 } else { |
|
2363 accepted = true; |
|
2364 } |
|
2365 |
|
2366 if (accepted) |
|
2367 d->h = temp; |
|
2368 |
|
2369 if (d->adv && txt.length() == 2) { |
|
2370 setFocusSection(d->ed->focusSection()+1); |
|
2371 overwrite = true; |
|
2372 } |
|
2373 } |
|
2374 break; |
|
2375 |
|
2376 case 1: |
|
2377 txt = QString::number(d->m); |
|
2378 if (d->overwrite || txt.length() == 2) { |
|
2379 if (!outOfRange(d->h, num, d->s)) { |
|
2380 accepted = true; |
|
2381 d->m = num; |
|
2382 } |
|
2383 } else { |
|
2384 txt += QString::number(num); |
|
2385 int temp = txt.toInt(); |
|
2386 if (temp > 59) |
|
2387 temp = num; |
|
2388 if (outOfRange(d->h, temp, d->s)) |
|
2389 txt = QString::number(d->m); |
|
2390 else { |
|
2391 accepted = true; |
|
2392 d->m = temp; |
|
2393 } |
|
2394 if (d->adv && txt.length() == 2) { |
|
2395 setFocusSection(d->ed->focusSection()+1); |
|
2396 overwrite = true; |
|
2397 } |
|
2398 } |
|
2399 break; |
|
2400 |
|
2401 case 2: |
|
2402 txt = QString::number(d->s); |
|
2403 if (d->overwrite || txt.length() == 2) { |
|
2404 if (!outOfRange(d->h, d->m, num)) { |
|
2405 accepted = true; |
|
2406 d->s = num; |
|
2407 } |
|
2408 } else { |
|
2409 txt += QString::number(num); |
|
2410 int temp = txt.toInt(); |
|
2411 if (temp > 59) |
|
2412 temp = num; |
|
2413 if (outOfRange(d->h, d->m, temp)) |
|
2414 txt = QString::number(d->s); |
|
2415 else { |
|
2416 accepted = true; |
|
2417 d->s = temp; |
|
2418 } |
|
2419 if (d->adv && txt.length() == 2) { |
|
2420 setFocusSection(d->ed->focusSection()+1); |
|
2421 overwrite = true; |
|
2422 } |
|
2423 } |
|
2424 break; |
|
2425 |
|
2426 case 3: |
|
2427 break; |
|
2428 |
|
2429 default: |
|
2430 break; |
|
2431 } |
|
2432 d->changed = !accepted; |
|
2433 if (accepted) |
|
2434 emit valueChanged(time()); |
|
2435 d->overwrite = overwrite; |
|
2436 d->timerId = startTimer(qApp->doubleClickInterval()*4); |
|
2437 d->ed->repaint(d->ed->rect()); |
|
2438 } |
|
2439 |
|
2440 |
|
2441 /*! |
|
2442 \internal |
|
2443 |
|
2444 Function which is called whenever the user tries to |
|
2445 remove the first number from \a sec by pressing the backspace key. |
|
2446 */ |
|
2447 |
|
2448 void Q3TimeEdit::removeFirstNumber(int sec) |
|
2449 { |
|
2450 if (sec == -1) |
|
2451 return; |
|
2452 sec = d->ed->mapSection(sec); |
|
2453 QString txt; |
|
2454 switch(sec) { |
|
2455 case 0: |
|
2456 txt = QString::number(d->h); |
|
2457 break; |
|
2458 case 1: |
|
2459 txt = QString::number(d->m); |
|
2460 break; |
|
2461 case 2: |
|
2462 txt = QString::number(d->s); |
|
2463 break; |
|
2464 } |
|
2465 txt = txt.mid(1, txt.length()) + QLatin1Char('0'); |
|
2466 switch(sec) { |
|
2467 case 0: |
|
2468 d->h = txt.toInt(); |
|
2469 break; |
|
2470 case 1: |
|
2471 d->m = txt.toInt(); |
|
2472 break; |
|
2473 case 2: |
|
2474 d->s = txt.toInt(); |
|
2475 break; |
|
2476 } |
|
2477 d->ed->repaint(d->ed->rect()); |
|
2478 } |
|
2479 |
|
2480 /*! \internal |
|
2481 |
|
2482 */ |
|
2483 void Q3TimeEdit::removeLastNumber(int sec) |
|
2484 { |
|
2485 if (sec == -1) |
|
2486 return; |
|
2487 sec = d->ed->mapSection(sec); |
|
2488 QString txt; |
|
2489 switch(sec) { |
|
2490 case 0: |
|
2491 txt = QString::number(d->h); |
|
2492 break; |
|
2493 case 1: |
|
2494 txt = QString::number(d->m); |
|
2495 break; |
|
2496 case 2: |
|
2497 txt = QString::number(d->s); |
|
2498 break; |
|
2499 } |
|
2500 txt = txt.mid(0, txt.length()-1); |
|
2501 switch(sec) { |
|
2502 case 0: |
|
2503 d->h = txt.toInt(); |
|
2504 break; |
|
2505 case 1: |
|
2506 d->m = txt.toInt(); |
|
2507 break; |
|
2508 case 2: |
|
2509 d->s = txt.toInt(); |
|
2510 break; |
|
2511 } |
|
2512 d->ed->repaint(d->ed->rect()); |
|
2513 } |
|
2514 |
|
2515 /*! \reimp |
|
2516 */ |
|
2517 void Q3TimeEdit::resizeEvent(QResizeEvent *) |
|
2518 { |
|
2519 d->controls->resize(width(), height()); |
|
2520 } |
|
2521 |
|
2522 /*! \reimp |
|
2523 */ |
|
2524 QSize Q3TimeEdit::sizeHint() const |
|
2525 { |
|
2526 ensurePolished(); |
|
2527 QFontMetrics fm(font()); |
|
2528 int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this); |
|
2529 int h = fm.lineSpacing() + 2; |
|
2530 int w = 2 + fm.width(QLatin1Char('9')) * 6 + fm.width(d->ed->separator()) * 2 + |
|
2531 d->controls->upRect().width() + fw * 4; |
|
2532 if (d->display & AMPM) { |
|
2533 if (lAM) |
|
2534 w += fm.width(*lAM) + 4; |
|
2535 else |
|
2536 w += fm.width(QString::fromLatin1("AM")) + 4; |
|
2537 } |
|
2538 |
|
2539 return QSize(w, qMax(h + fw * 2,20)).expandedTo(QApplication::globalStrut()); |
|
2540 } |
|
2541 |
|
2542 /*! \reimp |
|
2543 */ |
|
2544 QSize Q3TimeEdit::minimumSizeHint() const |
|
2545 { |
|
2546 return sizeHint(); |
|
2547 } |
|
2548 |
|
2549 /*! |
|
2550 \internal |
|
2551 Enables/disables the push buttons according to the min/max time |
|
2552 for this widget. |
|
2553 */ |
|
2554 |
|
2555 void Q3TimeEdit::updateButtons() |
|
2556 { |
|
2557 if (!isEnabled()) |
|
2558 return; |
|
2559 |
|
2560 bool upEnabled = time() < maxValue(); |
|
2561 bool downEnabled = time() > minValue(); |
|
2562 |
|
2563 d->controls->setUpEnabled(upEnabled); |
|
2564 d->controls->setDownEnabled(downEnabled); |
|
2565 } |
|
2566 |
|
2567 |
|
2568 class Q3DateTimeEditPrivate |
|
2569 { |
|
2570 public: |
|
2571 bool adv; |
|
2572 }; |
|
2573 |
|
2574 /*! |
|
2575 \class Q3DateTimeEdit |
|
2576 \brief The Q3DateTimeEdit class combines a Q3DateEdit and Q3TimeEdit |
|
2577 widget into a single widget for editing datetimes. |
|
2578 |
|
2579 \compat |
|
2580 |
|
2581 Q3DateTimeEdit consists of a Q3DateEdit and Q3TimeEdit widget placed |
|
2582 side by side and offers the functionality of both. The user can |
|
2583 edit the date and time by using the keyboard or the arrow keys to |
|
2584 increase/decrease date or time values. The Tab key can be used to |
|
2585 move from section to section within the Q3DateTimeEdit widget, and |
|
2586 the user can be moved automatically when they complete a section |
|
2587 using setAutoAdvance(). The datetime can be set with |
|
2588 setDateTime(). |
|
2589 |
|
2590 The date format is read from the system's locale settings. It is |
|
2591 set to year, month, day order if that is not possible. See |
|
2592 Q3DateEdit::setOrder() to change this. Times appear in the order |
|
2593 hours, minutes, seconds using the 24 hour clock. |
|
2594 |
|
2595 It is recommended that the Q3DateTimeEdit is initialised with a |
|
2596 datetime, e.g. |
|
2597 \snippet doc/src/snippets/code/src_qt3support_widgets_q3datetimeedit.cpp 2 |
|
2598 Here we've created a new Q3DateTimeEdit set to the current date and |
|
2599 time, and set the date to have a minimum date of now and a maximum |
|
2600 date of a week from now. |
|
2601 |
|
2602 Terminology: A Q3DateEdit widget consists of three 'sections', one |
|
2603 each for the year, month and day. Similarly a Q3TimeEdit consists |
|
2604 of three sections, one each for the hour, minute and second. The |
|
2605 character that separates each date section is specified with |
|
2606 setDateSeparator(); similarly setTimeSeparator() is used for the |
|
2607 time sections. |
|
2608 |
|
2609 \img datetimewidgets.png Date Time Widgets |
|
2610 |
|
2611 \sa Q3DateEdit Q3TimeEdit |
|
2612 */ |
|
2613 |
|
2614 /*! |
|
2615 Constructs an empty datetime edit with parent \a parent and called |
|
2616 \a name. |
|
2617 */ |
|
2618 Q3DateTimeEdit::Q3DateTimeEdit(QWidget * parent, const char * name) |
|
2619 : QWidget(parent, name) |
|
2620 { |
|
2621 init(); |
|
2622 } |
|
2623 |
|
2624 |
|
2625 /*! |
|
2626 \overload |
|
2627 |
|
2628 Constructs a datetime edit with the initial value \a datetime, |
|
2629 parent \a parent and called \a name. |
|
2630 */ |
|
2631 Q3DateTimeEdit::Q3DateTimeEdit(const QDateTime& datetime, |
|
2632 QWidget * parent, const char * name) |
|
2633 : QWidget(parent, name) |
|
2634 { |
|
2635 init(); |
|
2636 setDateTime(datetime); |
|
2637 } |
|
2638 |
|
2639 |
|
2640 |
|
2641 /*! |
|
2642 Destroys the object and frees any allocated resources. |
|
2643 */ |
|
2644 |
|
2645 Q3DateTimeEdit::~Q3DateTimeEdit() |
|
2646 { |
|
2647 delete d; |
|
2648 } |
|
2649 |
|
2650 |
|
2651 /*! \fn void Q3DateTimeEdit::resizeEvent(QResizeEvent *event) |
|
2652 \reimp |
|
2653 |
|
2654 Intercepts and handles the resize \a event, which hase a |
|
2655 special meaning for the Q3DateTimeEdit. |
|
2656 */ |
|
2657 void Q3DateTimeEdit::resizeEvent(QResizeEvent *) |
|
2658 { |
|
2659 int dw = de->sizeHint().width(); |
|
2660 int tw = te->sizeHint().width(); |
|
2661 int w = width(); |
|
2662 int h = height(); |
|
2663 int extra = w - (dw + tw); |
|
2664 |
|
2665 if (tw + extra < 0) { |
|
2666 dw = w; |
|
2667 } else { |
|
2668 dw += 9 * extra / 16; |
|
2669 } |
|
2670 tw = w - dw; |
|
2671 |
|
2672 de->setGeometry(0, 0, dw, h); |
|
2673 te->setGeometry(dw, 0, tw, h); |
|
2674 } |
|
2675 |
|
2676 /*! \reimp |
|
2677 */ |
|
2678 |
|
2679 QSize Q3DateTimeEdit::minimumSizeHint() const |
|
2680 { |
|
2681 QSize dsh = de->minimumSizeHint(); |
|
2682 QSize tsh = te->minimumSizeHint(); |
|
2683 return QSize(dsh.width() + tsh.width(), |
|
2684 qMax(dsh.height(), tsh.height())); |
|
2685 } |
|
2686 |
|
2687 /*! \internal |
|
2688 */ |
|
2689 |
|
2690 void Q3DateTimeEdit::init() |
|
2691 { |
|
2692 d = new Q3DateTimeEditPrivate(); |
|
2693 de = new Q3DateEdit(this, "qt_datetime_dateedit"); |
|
2694 te = new Q3TimeEdit(this, "qt_datetime_timeedit"); |
|
2695 d->adv = false; |
|
2696 connect(de, SIGNAL(valueChanged(QDate)), this, SLOT(newValue(QDate))); |
|
2697 connect(te, SIGNAL(valueChanged(QTime)), this, SLOT(newValue(QTime))); |
|
2698 setFocusProxy(de); |
|
2699 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); |
|
2700 } |
|
2701 |
|
2702 /*! \reimp |
|
2703 */ |
|
2704 |
|
2705 QSize Q3DateTimeEdit::sizeHint() const |
|
2706 { |
|
2707 ensurePolished(); |
|
2708 QSize dsh = de->sizeHint(); |
|
2709 QSize tsh = te->sizeHint(); |
|
2710 return QSize(dsh.width() + tsh.width(), |
|
2711 qMax(dsh.height(), tsh.height())); |
|
2712 } |
|
2713 |
|
2714 /*! |
|
2715 \property Q3DateTimeEdit::dateTime |
|
2716 \brief the editor's datetime value |
|
2717 |
|
2718 The datetime edit's datetime which may be an invalid datetime. |
|
2719 */ |
|
2720 |
|
2721 void Q3DateTimeEdit::setDateTime(const QDateTime & dt) |
|
2722 { |
|
2723 if (dt.isValid()) { |
|
2724 de->setDate(dt.date()); |
|
2725 te->setTime(dt.time()); |
|
2726 emit valueChanged(dt); |
|
2727 } |
|
2728 } |
|
2729 |
|
2730 QDateTime Q3DateTimeEdit::dateTime() const |
|
2731 { |
|
2732 return QDateTime(de->date(), te->time()); |
|
2733 } |
|
2734 |
|
2735 /*! |
|
2736 \fn void Q3DateTimeEdit::valueChanged(const QDateTime& datetime) |
|
2737 |
|
2738 This signal is emitted every time the date or time changes. The \a |
|
2739 datetime argument is the new datetime. |
|
2740 */ |
|
2741 |
|
2742 |
|
2743 /*! \internal |
|
2744 |
|
2745 Re-emits the value \a d. |
|
2746 */ |
|
2747 |
|
2748 void Q3DateTimeEdit::newValue(const QDate&) |
|
2749 { |
|
2750 QDateTime dt = dateTime(); |
|
2751 emit valueChanged(dt); |
|
2752 } |
|
2753 |
|
2754 /*! \internal |
|
2755 \overload |
|
2756 Re-emits the value \a t. |
|
2757 */ |
|
2758 |
|
2759 void Q3DateTimeEdit::newValue(const QTime&) |
|
2760 { |
|
2761 QDateTime dt = dateTime(); |
|
2762 emit valueChanged(dt); |
|
2763 } |
|
2764 |
|
2765 |
|
2766 /*! |
|
2767 Sets the auto advance property of the editor to \a advance. If set |
|
2768 to true, the editor will automatically advance focus to the next |
|
2769 date or time section if the user has completed a section. |
|
2770 */ |
|
2771 |
|
2772 void Q3DateTimeEdit::setAutoAdvance(bool advance) |
|
2773 { |
|
2774 de->setAutoAdvance(advance); |
|
2775 te->setAutoAdvance(advance); |
|
2776 } |
|
2777 |
|
2778 /*! |
|
2779 Returns true if auto-advance is enabled, otherwise returns false. |
|
2780 |
|
2781 \sa setAutoAdvance() |
|
2782 */ |
|
2783 |
|
2784 bool Q3DateTimeEdit::autoAdvance() const |
|
2785 { |
|
2786 return de->autoAdvance(); |
|
2787 } |
|
2788 |
|
2789 /*! |
|
2790 \fn Q3DateEdit* Q3DateTimeEdit::dateEdit() |
|
2791 |
|
2792 Returns the internal widget used for editing the date part of the |
|
2793 datetime. |
|
2794 */ |
|
2795 |
|
2796 /*! |
|
2797 \fn Q3TimeEdit* Q3DateTimeEdit::timeEdit() |
|
2798 |
|
2799 Returns the internal widget used for editing the time part of the |
|
2800 datetime. |
|
2801 */ |
|
2802 |
|
2803 QT_END_NAMESPACE |
|
2804 |
|
2805 #include "q3datetimeedit.moc" |
|
2806 |
|
2807 #endif |