1 | /* -*- C++ -*- |
2 | This file is part of the KDE libraries |
3 | Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) |
4 | (C) 1998-2001 Mirko Boehm (mirko@kde.org) |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library 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 GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #include "kdatepicker.h" |
22 | #include "kdatetable.h" |
23 | #include "kdatetable_p.h" |
24 | |
25 | #include <QApplication> |
26 | #include <QComboBox> |
27 | #include <QFont> |
28 | #include <QLayout> |
29 | #include <QKeyEvent> |
30 | #include <QMenu> |
31 | #include <QPainter> |
32 | #include <QStyle> |
33 | #include <QToolButton> |
34 | #include <QDoubleValidator> |
35 | #include <QWidget> |
36 | #include <QPushButton> |
37 | |
38 | #include <kcalendarsystem.h> |
39 | #include <kdebug.h> |
40 | #include <kdialog.h> |
41 | #include <kglobal.h> |
42 | #include <klineedit.h> |
43 | #include <klocale.h> |
44 | #include <knotification.h> |
45 | #include <kdeversion.h> |
46 | |
47 | #include <KoIcon.h> |
48 | #include "kptdebug.h" |
49 | |
50 | #include "kdatepicker.moc" |
51 | |
52 | namespace KPlato |
53 | { |
54 | |
55 | // Week numbers are defined by ISO 8601 |
56 | // See http://www.merlyn.demon.co.uk/weekinfo.htm for details |
57 | |
58 | class KDatePicker::KDatePickerPrivate |
59 | { |
60 | public: |
61 | KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {} |
62 | |
63 | void fillWeeksCombo(const QDate &date); |
64 | |
65 | QToolButton *closeButton; |
66 | QComboBox *selectWeek; |
67 | QPushButton *todayButton; |
68 | QBoxLayout *navigationLayout; |
69 | |
70 | /// the year forward button |
71 | QPushButton *yearForward; |
72 | /// the year backward button |
73 | QPushButton *yearBackward; |
74 | /// the month forward button |
75 | QPushButton *monthForward; |
76 | /// the month backward button |
77 | QPushButton *monthBackward; |
78 | /// the button for selecting the month directly |
79 | QPushButton *selectMonth; |
80 | /// the button for selecting the year directly |
81 | QPushButton *selectYear; |
82 | /// the line edit to enter the date directly |
83 | QLineEdit *line; |
84 | /// the validator for the line edit: |
85 | KDateValidator *val; |
86 | /// the date table |
87 | KDateTable *table; |
88 | /// the widest month string in pixels: |
89 | QSize maxMonthRect; |
90 | |
91 | /// the font size for the widget |
92 | int fontsize; |
93 | }; |
94 | |
95 | void KDatePicker::fillWeeksCombo(const QDate &date) |
96 | { |
97 | // every year can have a different number of weeks |
98 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
99 | |
100 | // it could be that we had 53,1..52 and now 1..53 which is the same number but different |
101 | // so always fill with new values |
102 | |
103 | d->selectWeek->clear(); |
104 | |
105 | // We show all week numbers for all weeks between first day of year to last day of year |
106 | // This of course can be a list like 53,1,2..52 |
107 | |
108 | QDate day; |
109 | int year = calendar->year(date); |
110 | calendar->setDate(day, year, 1, 1); |
111 | int lastMonth = calendar->monthsInYear(day); |
112 | QDate lastDay, firstDayOfLastMonth; |
113 | calendar->setDate(firstDayOfLastMonth, year, lastMonth, 1); |
114 | calendar->setDate(lastDay, year, lastMonth, calendar->daysInMonth(firstDayOfLastMonth)); |
115 | |
116 | for (; day <= lastDay ; day = calendar->addDays(day, 7 /*calendar->daysOfWeek()*/) ) |
117 | { |
118 | #if KDE_IS_VERSION(4,7,0) |
119 | const int weekNumber = calendar->week(day, &year); |
120 | #else |
121 | const int weekNumber = calendar->weekNumber(day, &year); |
122 | #endif |
123 | QString week = i18n("Week %1" , weekNumber); |
124 | if ( year != calendar->year(day) ) week += '*'; // show that this is a week from a different year |
125 | d->selectWeek->addItem(week); |
126 | |
127 | // make sure that the week of the lastDay is always inserted: in Chinese calendar |
128 | // system, this is not always the case |
129 | if(day < lastDay && day.daysTo(lastDay) < 7 && |
130 | #if KDE_IS_VERSION(4,7,0) |
131 | calendar->week(day) != calendar->week(lastDay)) |
132 | #else |
133 | calendar->weekNumber(day) != calendar->weekNumber(lastDay)) |
134 | #endif |
135 | day = lastDay.addDays(-7); |
136 | } |
137 | } |
138 | |
139 | KDatePicker::KDatePicker(QWidget* parent) |
140 | : QFrame(parent),d(new KDatePickerPrivate()) |
141 | { |
142 | init( QDate::currentDate() ); |
143 | } |
144 | |
145 | KDatePicker::KDatePicker(const QDate& dt, QWidget* parent) |
146 | : QFrame(parent),d(new KDatePickerPrivate()) |
147 | { |
148 | init( dt ); |
149 | } |
150 | |
151 | void KDatePicker::init( const QDate &dt ) |
152 | { |
153 | setFocusPolicy( Qt::StrongFocus ); |
154 | |
155 | QBoxLayout * topLayout = new QVBoxLayout(this); |
156 | topLayout->setSpacing(0); |
157 | topLayout->setMargin(0); |
158 | |
159 | d->navigationLayout = new QHBoxLayout(); |
160 | d->navigationLayout->setSpacing(0); |
161 | d->navigationLayout->setMargin(0); |
162 | topLayout->addLayout(d->navigationLayout); |
163 | d->navigationLayout->addStretch(); |
164 | |
165 | d->yearBackward = new QPushButton(this); |
166 | //d->yearBackward->setAutoRaise(true); |
167 | d->yearBackward->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
168 | d->yearBackward->setMaximumSize( QSize( 30, 30 ) ); |
169 | d->navigationLayout->addWidget(d->yearBackward); |
170 | d->yearBackward->installEventFilter( this ); |
171 | |
172 | d->monthBackward = new QPushButton(this); |
173 | //d->monthBackward ->setAutoRaise(true); |
174 | d->monthBackward->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
175 | d->monthBackward->setMaximumSize( QSize( 30, 30 ) ); |
176 | d->navigationLayout->addWidget(d->monthBackward); |
177 | d->navigationLayout->addSpacing(KDialog::spacingHint()); |
178 | d->monthBackward->installEventFilter( this ); |
179 | |
180 | d->selectMonth = new QPushButton(this); |
181 | //d->selectMonth ->setAutoRaise(true); |
182 | d->selectMonth->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
183 | d->selectMonth->setMaximumSize( QSize( 30, 30 ) ); |
184 | d->navigationLayout->addWidget(d->selectMonth); |
185 | d->selectMonth->installEventFilter( this ); |
186 | |
187 | d->selectYear = new QPushButton(this); |
188 | d->selectYear->setCheckable(true); |
189 | //d->selectYear->setAutoRaise(true); |
190 | d->selectYear->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
191 | d->selectYear->setMaximumSize( QSize( 30, 30 ) ); |
192 | d->navigationLayout->addWidget(d->selectYear); |
193 | d->navigationLayout->addSpacing(KDialog::spacingHint()); |
194 | d->selectYear->installEventFilter( this ); |
195 | |
196 | d->monthForward = new QPushButton(this); |
197 | //d->monthForward ->setAutoRaise(true); |
198 | d->monthForward->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
199 | d->monthForward->setMaximumSize( QSize( 30, 30 ) ); |
200 | d->navigationLayout->addWidget(d->monthForward); |
201 | |
202 | d->yearForward = new QPushButton(this); |
203 | //d->yearForward ->setFlat(true); |
204 | d->yearForward->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
205 | d->yearForward->setMaximumSize( QSize( 30, 30 ) ); |
206 | d->navigationLayout->addWidget(d->yearForward); |
207 | d->yearForward->installEventFilter( this ); |
208 | |
209 | d->navigationLayout->addStretch(); |
210 | |
211 | d->line = new KLineEdit(this); |
212 | d->val = new KDateValidator(this); |
213 | |
214 | Frame *f = new Frame( this ); |
215 | topLayout->addWidget( f ); |
216 | QVBoxLayout *l = new QVBoxLayout( f ); |
217 | |
218 | d->table = new KDateTable(f); |
219 | connect( d->table, SIGNAL( focusChanged( QFocusEvent* ) ), f, SLOT( updateFocus( QFocusEvent* ) ) ); |
220 | l->addWidget( d->table ); |
221 | f->setFocusProxy( d->table ); |
222 | d->table->installEventFilter( this ); |
223 | |
224 | d->fontsize = KGlobalSettings::generalFont().pointSize(); |
225 | if (d->fontsize == -1) |
226 | d->fontsize = QFontInfo(KGlobalSettings::generalFont()).pointSize(); |
227 | |
228 | d->fontsize++; // Make a little bigger |
229 | |
230 | d->selectWeek = new QComboBox(this); // read only week selection |
231 | d->selectWeek->installEventFilter( this ); |
232 | |
233 | d->todayButton = new QPushButton(this); |
234 | d->todayButton->setIcon(koIcon("go-jump-today" )); |
235 | d->todayButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); |
236 | d->todayButton->setMaximumSize( QSize( 25, 25 ) ); |
237 | d->todayButton->installEventFilter( this ); |
238 | |
239 | d->yearForward->setToolTip(i18n("Next year" )); |
240 | d->yearBackward->setToolTip(i18n("Previous year" )); |
241 | d->monthForward->setToolTip(i18n("Next month" )); |
242 | d->monthBackward->setToolTip(i18n("Previous month" )); |
243 | d->selectWeek->setToolTip(i18n("Select a week" )); |
244 | d->selectMonth->setToolTip(i18n("Select a month" )); |
245 | d->selectYear->setToolTip(i18n("Select a year" )); |
246 | d->todayButton->setToolTip(i18n("Select the current day" )); |
247 | |
248 | // ----- |
249 | setFontSize(d->fontsize); |
250 | d->line->setValidator(d->val); |
251 | d->line->installEventFilter( this ); |
252 | if ( QApplication::isRightToLeft() ) |
253 | { |
254 | d->yearForward->setIcon(koIcon("arrow-left-double" )); |
255 | d->yearBackward->setIcon(koIcon("arrow-right-double" )); |
256 | d->monthForward->setIcon(koIcon("arrow-left" )); |
257 | d->monthBackward->setIcon(koIcon("arrow-right" )); |
258 | } |
259 | else |
260 | { |
261 | d->yearForward->setIcon(koIcon("arrow-right-double" )); |
262 | d->yearBackward->setIcon(koIcon("arrow-left-double" )); |
263 | d->monthForward->setIcon(koIcon("arrow-right" )); |
264 | d->monthBackward->setIcon(koIcon("arrow-left" )); |
265 | } |
266 | |
267 | connect(d->table, SIGNAL(dateChanged(const QDate&)), SLOT(dateChangedSlot(const QDate&))); |
268 | connect(d->table, SIGNAL(tableClicked()), SLOT(tableClickedSlot())); |
269 | connect(d->monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked())); |
270 | connect(d->monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked())); |
271 | connect(d->yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked())); |
272 | connect(d->yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked())); |
273 | connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int))); |
274 | connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked())); |
275 | connect(d->selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked())); |
276 | connect(d->selectYear, SIGNAL(toggled(bool)), SLOT(selectYearClicked())); |
277 | connect(d->line, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); |
278 | d->table->setFocus(); |
279 | |
280 | |
281 | QBoxLayout * bottomLayout = new QHBoxLayout(); |
282 | bottomLayout->setMargin(0); |
283 | bottomLayout->setSpacing(0); |
284 | topLayout->addLayout(bottomLayout); |
285 | |
286 | bottomLayout->addWidget(d->todayButton); |
287 | bottomLayout->addWidget(d->line); |
288 | bottomLayout->addWidget(d->selectWeek); |
289 | |
290 | d->table->setDate(dt); |
291 | dateChangedSlot(dt); // needed because table emits changed only when newDate != oldDate |
292 | } |
293 | |
294 | KDatePicker::~KDatePicker() |
295 | { |
296 | delete d; |
297 | } |
298 | |
299 | bool |
300 | KDatePicker::eventFilter(QObject *o, QEvent *e ) |
301 | { |
302 | /* if ( e->type() == QEvent::KeyPress ) { |
303 | QKeyEvent *k = (QKeyEvent *)e; |
304 | |
305 | if ( (k->key() == Qt::Key_PageUp) || |
306 | (k->key() == Qt::Key_PageDown) || |
307 | (k->key() == Qt::Key_Up) || |
308 | (k->key() == Qt::Key_Down) ) |
309 | { |
310 | QApplication::sendEvent( d->table, e ); |
311 | d->table->setFocus(); |
312 | return true; // eat event |
313 | } |
314 | }*/ |
315 | if ( o != this && ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut ) ) { |
316 | update(); |
317 | } |
318 | return QFrame::eventFilter( o, e ); |
319 | } |
320 | |
321 | void |
322 | KDatePicker::resizeEvent(QResizeEvent* e) |
323 | { |
324 | QWidget::resizeEvent(e); |
325 | } |
326 | |
327 | void |
328 | KDatePicker::paintEvent(QPaintEvent *e) |
329 | { |
330 | Q_UNUSED(e); |
331 | //kDebug(planDbg())<<e; |
332 | QPainter paint(this); |
333 | drawFrame(&paint); |
334 | } |
335 | |
336 | void |
337 | KDatePicker::drawFrame(QPainter *p) |
338 | { |
339 | QPoint p1, p2; |
340 | QStyleOptionFrame opt; |
341 | opt.init(this); |
342 | QList<QWidget*> lst = findChildren<QWidget*>(); |
343 | foreach ( QWidget *w, lst ) { |
344 | if ( w->hasFocus() ) { |
345 | opt.state |= QStyle::State_HasFocus; |
346 | break; |
347 | } |
348 | } |
349 | int frameShape = frameStyle() & QFrame::Shape_Mask; |
350 | int frameShadow = frameStyle() & QFrame::Shadow_Mask; |
351 | |
352 | int lw = 0; |
353 | int mlw = 0; |
354 | opt.rect = frameRect(); |
355 | switch (frameShape) { |
356 | case QFrame::Box: |
357 | case QFrame::HLine: |
358 | case QFrame::VLine: |
359 | case QFrame::StyledPanel: |
360 | lw = lineWidth(); |
361 | mlw = midLineWidth(); |
362 | break; |
363 | default: |
364 | // most frame styles do not handle customized line and midline widths |
365 | // (see updateFrameWidth()). |
366 | lw = frameWidth(); |
367 | break; |
368 | } |
369 | opt.lineWidth = lw; |
370 | opt.midLineWidth = mlw; |
371 | if (frameShadow == Sunken) |
372 | opt.state |= QStyle::State_Sunken; |
373 | else if (frameShadow == Raised) |
374 | opt.state |= QStyle::State_Raised; |
375 | |
376 | switch (frameShape) { |
377 | case Box: |
378 | if (frameShadow == Plain) |
379 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
380 | else |
381 | qDrawShadeRect(p, opt.rect, opt.palette, frameShadow == Sunken, lw, mlw); |
382 | break; |
383 | |
384 | |
385 | case StyledPanel: |
386 | style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this); |
387 | break; |
388 | |
389 | case Panel: |
390 | if (frameShadow == Plain) |
391 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
392 | else |
393 | qDrawShadePanel(p, opt.rect, opt.palette, frameShadow == Sunken, lw); |
394 | break; |
395 | |
396 | case WinPanel: |
397 | if (frameShadow == Plain) |
398 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
399 | else |
400 | qDrawWinPanel(p, opt.rect, opt.palette, frameShadow == Sunken); |
401 | break; |
402 | case HLine: |
403 | case VLine: |
404 | if (frameShape == HLine) { |
405 | p1 = QPoint(opt.rect.x(), opt.rect.height() / 2); |
406 | p2 = QPoint(opt.rect.x() + opt.rect.width(), p1.y()); |
407 | } else { |
408 | p1 = QPoint(opt.rect.x()+opt.rect.width() / 2, 0); |
409 | p2 = QPoint(p1.x(), opt.rect.height()); |
410 | } |
411 | if (frameShadow == Plain) { |
412 | QPen oldPen = p->pen(); |
413 | p->setPen(QPen(opt.palette.foreground().color(), lw)); |
414 | p->drawLine(p1, p2); |
415 | p->setPen(oldPen); |
416 | } else { |
417 | qDrawShadeLine(p, p1, p2, opt.palette, frameShadow == Sunken, lw, mlw); |
418 | } |
419 | break; |
420 | } |
421 | } |
422 | |
423 | void |
424 | KDatePicker::dateChangedSlot(const QDate &date) |
425 | { |
426 | kDebug(planDbg())<< "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." ; |
427 | |
428 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
429 | |
430 | d->line->setText(KGlobal::locale()->formatDate(date, KLocale::ShortDate)); |
431 | d->selectMonth->setText(calendar->monthName(date, KCalendarSystem::ShortName)); |
432 | fillWeeksCombo(date); |
433 | |
434 | // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week |
435 | QDate firstDay; |
436 | calendar->setDate(firstDay, calendar->year(date), 1, 1); |
437 | d->selectWeek->setCurrentIndex((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/); |
438 | d->selectYear->setText(calendar->formatDate(date, KLocale::Year, KLocale::ShortNumber)); |
439 | |
440 | emit(dateChanged(date)); |
441 | } |
442 | |
443 | void |
444 | KDatePicker::tableClickedSlot() |
445 | { |
446 | kDebug(planDbg())<< "KDatePicker::tableClickedSlot: table clicked." ; |
447 | emit(dateSelected(d->table->date())); |
448 | emit(tableClicked()); |
449 | } |
450 | |
451 | const QDate & |
452 | KDatePicker::date() const |
453 | { |
454 | return d->table->date(); |
455 | } |
456 | |
457 | bool |
458 | KDatePicker::setDate(const QDate& date) |
459 | { |
460 | if(date.isValid()) |
461 | { |
462 | d->table->setDate(date); // this also emits dateChanged() which then calls our dateChangedSlot() |
463 | return true; |
464 | } |
465 | else |
466 | { |
467 | kDebug(planDbg())<<"KDatePicker::setDate: refusing to set invalid date." ; |
468 | return false; |
469 | } |
470 | } |
471 | |
472 | void |
473 | KDatePicker::monthForwardClicked() |
474 | { |
475 | QDate temp; |
476 | temp = KGlobal::locale()->calendar()->addMonths( d->table->date(), 1 ); |
477 | |
478 | setDate( temp ); |
479 | } |
480 | |
481 | void |
482 | KDatePicker::monthBackwardClicked() |
483 | { |
484 | QDate temp; |
485 | temp = KGlobal::locale()->calendar()->addMonths( d->table->date(), -1 ); |
486 | |
487 | setDate( temp ); |
488 | } |
489 | |
490 | void |
491 | KDatePicker::yearForwardClicked() |
492 | { |
493 | QDate temp; |
494 | temp = KGlobal::locale()->calendar()->addYears( d->table->date(), 1 ); |
495 | |
496 | setDate( temp ); |
497 | } |
498 | |
499 | void |
500 | KDatePicker::yearBackwardClicked() |
501 | { |
502 | QDate temp; |
503 | temp = KGlobal::locale()->calendar()->addYears( d->table->date(), -1 ); |
504 | |
505 | setDate( temp ); |
506 | } |
507 | |
508 | void |
509 | KDatePicker::weekSelected(int week) |
510 | { |
511 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
512 | |
513 | QDate date = d->table->date(); |
514 | int year = calendar->year(date); |
515 | |
516 | calendar->setDate(date, year, 1, 1); // first day of selected year |
517 | |
518 | // calculate the first day in the selected week (day 1 is first day of week) |
519 | date = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1); |
520 | |
521 | setDate(date); |
522 | } |
523 | |
524 | void |
525 | KDatePicker::selectMonthClicked() |
526 | { |
527 | // every year can have different month names (in some calendar systems) |
528 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
529 | QDate date = d->table->date(); |
530 | const int months = calendar->monthsInYear(date); |
531 | |
532 | QMenu (d->selectMonth); |
533 | |
534 | for (int i = 1; i <= months; i++) |
535 | popup.addAction(calendar->monthName(i, calendar->year(date)))->setData(i); |
536 | |
537 | //QMenuItem *item = popup.findItem (calendar->month(date) - 1); |
538 | QAction *item=popup.actions()[calendar->month(date)-1]; |
539 | if (item) // if this happens the above should already given an assertion |
540 | popup.setActiveAction(item); |
541 | |
542 | if ( (item = popup.exec(d->selectMonth->mapToGlobal(QPoint(0, 0)), item)) == 0 ) return; // canceled |
543 | |
544 | int day = calendar->day(date); |
545 | // ----- construct a valid date in this month: |
546 | calendar->setDate(date, calendar->year(date), item->data().toInt(), 1); |
547 | date = date.addDays(qMin(day, calendar->daysInMonth(date)) - 1); |
548 | // ----- set this month |
549 | setDate(date); |
550 | } |
551 | |
552 | void |
553 | KDatePicker::selectYearClicked() |
554 | { |
555 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
556 | |
557 | if (!d->selectYear->isChecked ()) |
558 | { |
559 | return; |
560 | } |
561 | |
562 | int year; |
563 | KPopupFrame* = new KPopupFrame(this); |
564 | KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup); |
565 | // ----- |
566 | picker->resize(picker->sizeHint()); |
567 | picker->setYear( d->table->date().year() ); |
568 | picker->selectAll(); |
569 | popup->setMainWidget(picker); |
570 | connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); |
571 | picker->setFocus(); |
572 | if(popup->exec(d->selectYear->mapToGlobal(QPoint(0, d->selectMonth->height())))) |
573 | { |
574 | QDate date; |
575 | int day; |
576 | // ----- |
577 | year=picker->getYear(); |
578 | date=d->table->date(); |
579 | day=calendar->day(date); |
580 | // ----- construct a valid date in this month: |
581 | //date.setDate(year, date.month(), 1); |
582 | //date.setDate(year, date.month(), qMin(day, date.daysInMonth())); |
583 | calendar->setDate(date, year, calendar->month(date), |
584 | qMin(day, calendar->daysInMonth(date))); |
585 | // ----- set this month |
586 | setDate(date); |
587 | } else { |
588 | //KNotification::beep(); |
589 | } |
590 | d->selectYear->setChecked( false ); |
591 | delete popup; |
592 | } |
593 | |
594 | // ####### KDE4: setEnabled isn't virtual anymore, so this isn't polymorphic. |
595 | // Better reimplement changeEvent() instead. |
596 | void |
597 | KDatePicker::setEnabled(bool enable) |
598 | { |
599 | QWidget *widgets[]= { |
600 | d->yearForward, d->yearBackward, d->monthForward, d->monthBackward, |
601 | d->selectMonth, d->selectYear, |
602 | d->line, d->table, d->selectWeek, d->todayButton }; |
603 | const int Size=sizeof(widgets)/sizeof(widgets[0]); |
604 | int count; |
605 | // ----- |
606 | for(count=0; count<Size; ++count) |
607 | { |
608 | widgets[count]->setEnabled(enable); |
609 | } |
610 | } |
611 | |
612 | KDateTable *KDatePicker::dateTable() const |
613 | { |
614 | return d->table; |
615 | } |
616 | |
617 | void |
618 | KDatePicker::lineEnterPressed() |
619 | { |
620 | QDate temp; |
621 | // ----- |
622 | if(d->val->date(d->line->text(), temp)==QValidator::Acceptable) |
623 | { |
624 | kDebug(planDbg())<< "KDatePicker::lineEnterPressed: valid date entered." ; |
625 | emit(dateEntered(temp)); |
626 | setDate(temp); |
627 | } else { |
628 | KNotification::beep(); |
629 | kDebug(planDbg())<< "KDatePicker::lineEnterPressed: invalid date entered." ; |
630 | } |
631 | } |
632 | |
633 | void |
634 | KDatePicker::todayButtonClicked() |
635 | { |
636 | setDate(QDate::currentDate()); |
637 | } |
638 | |
639 | QSize |
640 | KDatePicker::sizeHint() const |
641 | { |
642 | return QWidget::sizeHint(); |
643 | } |
644 | |
645 | void |
646 | KDatePicker::setFontSize(int s) |
647 | { |
648 | QWidget *buttons[]= { |
649 | // yearBackward, |
650 | // monthBackward, |
651 | d->selectMonth, |
652 | d->selectYear, |
653 | // monthForward, |
654 | // yearForward |
655 | }; |
656 | const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); |
657 | int count; |
658 | QFont font; |
659 | QRect r; |
660 | // ----- |
661 | d->fontsize=s; |
662 | for(count=0; count<NoOfButtons; ++count) |
663 | { |
664 | font=buttons[count]->font(); |
665 | font.setPointSize(s); |
666 | buttons[count]->setFont(font); |
667 | } |
668 | QFontMetrics metrics(d->selectMonth->fontMetrics()); |
669 | |
670 | for (int i = 1; ; ++i) |
671 | { |
672 | QString str = KGlobal::locale()->calendar()->monthName(i, |
673 | KGlobal::locale()->calendar()->year(d->table->date()), KCalendarSystem::ShortName); |
674 | if (str.isNull()) break; |
675 | r=metrics.boundingRect(str); |
676 | d->maxMonthRect.setWidth(qMax(r.width(), d->maxMonthRect.width())); |
677 | d->maxMonthRect.setHeight(qMax(r.height(), d->maxMonthRect.height())); |
678 | } |
679 | |
680 | QStyleOptionToolButton opt; |
681 | |
682 | // stolen from KToolBarButton |
683 | opt.init(this); |
684 | opt.font = d->selectMonth->font(); |
685 | opt.icon = d->selectMonth->icon(); |
686 | opt.text = d->selectMonth->text(); |
687 | opt.features = d->selectMonth->menu() ? QStyleOptionToolButton::Menu : QStyleOptionToolButton::None; //### FIXME: delay? |
688 | opt.subControls = QStyle::SC_All; |
689 | opt.activeSubControls = 0; //### FIXME: !! |
690 | |
691 | QSize metricBound = style()->sizeFromContents(QStyle::CT_ToolButton, |
692 | &opt, |
693 | d->maxMonthRect, d->selectMonth); |
694 | d->selectMonth->setMinimumSize(metricBound); |
695 | |
696 | d->table->setFontSize(s); |
697 | } |
698 | |
699 | int KDatePicker::fontSize() const |
700 | { |
701 | return d->fontsize; |
702 | } |
703 | |
704 | |
705 | void |
706 | KDatePicker::setCloseButton( bool enable ) |
707 | { |
708 | if ( enable == (d->closeButton != 0L) ) |
709 | return; |
710 | |
711 | if ( enable ) { |
712 | d->closeButton = new QToolButton( this ); |
713 | d->closeButton->setAutoRaise(true); |
714 | d->navigationLayout->addSpacing(KDialog::spacingHint()); |
715 | d->navigationLayout->addWidget(d->closeButton); |
716 | d->closeButton->setToolTip(i18n("Close" )); |
717 | d->closeButton->setIcon(koIcon("list-remove" )); |
718 | connect( d->closeButton, SIGNAL( clicked() ), |
719 | topLevelWidget(), SLOT( close() ) ); |
720 | } |
721 | else { |
722 | delete d->closeButton; |
723 | d->closeButton = 0L; |
724 | } |
725 | |
726 | updateGeometry(); |
727 | } |
728 | |
729 | bool KDatePicker::hasCloseButton() const |
730 | { |
731 | return (d->closeButton); |
732 | } |
733 | |
734 | } //namespace KPlato |
735 | |