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 | /////////////////// KDateTable widget class ////////////////////// |
22 | // |
23 | // Copyright (C) 1997 Tim D. Gilman |
24 | // (C) 1998-2001 Mirko Boehm |
25 | // Written using Qt (http://www.troll.no) for the |
26 | // KDE project (http://www.kde.org) |
27 | // |
28 | // This is a support class for the KDatePicker class. It just |
29 | // draws the calendar table without titles, but could theoretically |
30 | // be used as a standalone. |
31 | // |
32 | // When a date is selected by the user, it emits a signal: |
33 | // dateSelected(QDate) |
34 | |
35 | #include "kdatetable.h" |
36 | #include "kdatetable_p.h" |
37 | |
38 | #include <kdeversion.h> |
39 | #include <kconfig.h> |
40 | #include <kcolorscheme.h> |
41 | #include <kglobal.h> |
42 | #include <kglobalsettings.h> |
43 | #include <klocale.h> |
44 | #include <kdebug.h> |
45 | #include <knotification.h> |
46 | #include <kcalendarsystem.h> |
47 | #include <kshortcut.h> |
48 | #include <kstandardshortcut.h> |
49 | #include "kdatepicker.h" |
50 | #include "kmenu.h" |
51 | #include "kactioncollection.h" |
52 | #include "kaction.h" |
53 | |
54 | #include <QDate> |
55 | #include <QCharRef> |
56 | #include <QPen> |
57 | #include <QPainter> |
58 | #include <QDialog> |
59 | #include <QActionEvent> |
60 | #include <QHash> |
61 | #include <QApplication> |
62 | #include <QToolTip> |
63 | |
64 | #include <assert.h> |
65 | |
66 | #include <cmath> |
67 | |
68 | #include "kptdebug.h" |
69 | |
70 | namespace KPlato |
71 | { |
72 | |
73 | Frame::Frame( QWidget *parent ) |
74 | : QFrame( parent ) |
75 | { |
76 | setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); |
77 | setFrameStyle(QFrame::StyledPanel | QFrame::Plain); |
78 | setLineWidth(1); |
79 | } |
80 | |
81 | void Frame::updateFocus(QFocusEvent *e) |
82 | { |
83 | if ( e->type() == QEvent::FocusIn ) { |
84 | setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); |
85 | } else { |
86 | setFrameStyle(QFrame::StyledPanel | QFrame::Plain); |
87 | } |
88 | update(); |
89 | } |
90 | |
91 | void Frame::paintEvent(QPaintEvent *e) |
92 | { |
93 | Q_UNUSED(e); |
94 | //kDebug(planDbg())<<e; |
95 | QPainter paint(this); |
96 | drawFrame(&paint); |
97 | } |
98 | |
99 | void Frame::drawFrame(QPainter *p) |
100 | { |
101 | QPoint p1, p2; |
102 | QStyleOptionFrame opt; |
103 | opt.init(this); |
104 | if ( hasFocus() ) { |
105 | opt.state |= QStyle::State_HasFocus; |
106 | } |
107 | int frameShape = frameStyle() & QFrame::Shape_Mask; |
108 | int frameShadow = frameStyle() & QFrame::Shadow_Mask; |
109 | |
110 | int lw = 0; |
111 | int mlw = 0; |
112 | opt.rect = frameRect(); |
113 | switch (frameShape) { |
114 | case QFrame::Box: |
115 | case QFrame::HLine: |
116 | case QFrame::VLine: |
117 | case QFrame::StyledPanel: |
118 | lw = lineWidth(); |
119 | mlw = midLineWidth(); |
120 | break; |
121 | default: |
122 | // most frame styles do not handle customized line and midline widths |
123 | // (see updateFrameWidth()). |
124 | lw = frameWidth(); |
125 | break; |
126 | } |
127 | opt.lineWidth = lw; |
128 | opt.midLineWidth = mlw; |
129 | if (frameShadow == Sunken) |
130 | opt.state |= QStyle::State_Sunken; |
131 | else if (frameShadow == Raised) |
132 | opt.state |= QStyle::State_Raised; |
133 | |
134 | switch (frameShape) { |
135 | case Box: |
136 | if (frameShadow == Plain) |
137 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
138 | else |
139 | qDrawShadeRect(p, opt.rect, opt.palette, frameShadow == Sunken, lw, mlw); |
140 | break; |
141 | |
142 | |
143 | case StyledPanel: |
144 | style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this); |
145 | break; |
146 | |
147 | case Panel: |
148 | if (frameShadow == Plain) |
149 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
150 | else |
151 | qDrawShadePanel(p, opt.rect, opt.palette, frameShadow == Sunken, lw); |
152 | break; |
153 | |
154 | case WinPanel: |
155 | if (frameShadow == Plain) |
156 | qDrawPlainRect(p, opt.rect, opt.palette.foreground().color(), lw); |
157 | else |
158 | qDrawWinPanel(p, opt.rect, opt.palette, frameShadow == Sunken); |
159 | break; |
160 | case HLine: |
161 | case VLine: |
162 | if (frameShape == HLine) { |
163 | p1 = QPoint(opt.rect.x(), opt.rect.height() / 2); |
164 | p2 = QPoint(opt.rect.x() + opt.rect.width(), p1.y()); |
165 | } else { |
166 | p1 = QPoint(opt.rect.x()+opt.rect.width() / 2, 0); |
167 | p2 = QPoint(p1.x(), opt.rect.height()); |
168 | } |
169 | if (frameShadow == Plain) { |
170 | QPen oldPen = p->pen(); |
171 | p->setPen(QPen(opt.palette.foreground().color(), lw)); |
172 | p->drawLine(p1, p2); |
173 | p->setPen(oldPen); |
174 | } else { |
175 | qDrawShadeLine(p, p1, p2, opt.palette, frameShadow == Sunken, lw, mlw); |
176 | } |
177 | break; |
178 | } |
179 | } |
180 | |
181 | |
182 | class KDateTable::KDateTablePrivate |
183 | { |
184 | public: |
185 | KDateTablePrivate(KDateTable *q): q(q) |
186 | { |
187 | popupMenuEnabled=false; |
188 | m_selectionmode = KDateTable::SingleSelection; |
189 | m_paintweeknumbers = false; |
190 | m_model = 0; |
191 | m_grid = false; |
192 | } |
193 | |
194 | ~KDateTablePrivate() |
195 | { |
196 | foreach( KDateTableDateDelegate *delegate, customPaintingModes ) { |
197 | delete delegate; |
198 | } |
199 | } |
200 | |
201 | void nextMonth(); |
202 | void previousMonth(); |
203 | void beginningOfMonth(); |
204 | void endOfMonth(); |
205 | void beginningOfWeek(); |
206 | void endOfWeek(); |
207 | |
208 | KDateTable *q; |
209 | |
210 | /** |
211 | * The font size of the displayed text. |
212 | */ |
213 | int fontsize; |
214 | /** |
215 | * The currently selected date. |
216 | */ |
217 | QDate mDate; |
218 | /** |
219 | * The day of the first day in the month [1..7]. |
220 | */ |
221 | int firstday; |
222 | /** |
223 | * The number of days in the current month. |
224 | */ |
225 | int numdays; |
226 | /** |
227 | * The number of days in the previous month. |
228 | */ |
229 | int numDaysPrevMonth; |
230 | /** |
231 | * Save the size of the largest used cell content. |
232 | */ |
233 | QRectF maxCell; |
234 | |
235 | bool ; |
236 | |
237 | //-----> |
238 | QHash <QString, KDateTableDateDelegate*> customPaintingModes; |
239 | |
240 | KDateTableDataModel *m_model; |
241 | |
242 | KDateTableDateDelegate *m_dateDelegate; |
243 | KDateTableWeekDayDelegate *m_weekDayDelegate; |
244 | KDateTableWeekNumberDelegate *m_weekNumberDelegate; |
245 | |
246 | StyleOptionViewItem m_styleOptionDate; |
247 | StyleOptionHeader m_styleOptionWeekDay; |
248 | StyleOptionHeader m_styleOptionWeekNumber; |
249 | |
250 | QList<QDate> m_selectedDates; |
251 | SelectionMode m_selectionmode; |
252 | |
253 | bool m_paintweeknumbers; |
254 | bool m_grid; |
255 | }; |
256 | |
257 | class KPopupFrame:: |
258 | { |
259 | public: |
260 | (KPopupFrame *q): |
261 | q(q), |
262 | result(0), // rejected |
263 | main(0) {} |
264 | |
265 | KPopupFrame *; |
266 | |
267 | /** |
268 | * The result. It is returned from exec() when the popup window closes. |
269 | */ |
270 | int ; |
271 | /** |
272 | * The only subwidget that uses the whole dialog window. |
273 | */ |
274 | QWidget *main; |
275 | }; |
276 | |
277 | |
278 | KDateValidator::KDateValidator(QWidget* parent) |
279 | : QValidator(parent) |
280 | { |
281 | } |
282 | |
283 | QValidator::State |
284 | KDateValidator::validate(QString& text, int&) const |
285 | { |
286 | QDate temp; |
287 | // ----- everything is tested in date(): |
288 | return date(text, temp); |
289 | } |
290 | |
291 | QValidator::State |
292 | KDateValidator::date(const QString& text, QDate& d) const |
293 | { |
294 | QDate tmp = KGlobal::locale()->readDate(text); |
295 | if (!tmp.isNull()) |
296 | { |
297 | d = tmp; |
298 | return Acceptable; |
299 | } else |
300 | return QValidator::Intermediate; |
301 | } |
302 | |
303 | void |
304 | KDateValidator::fixup( QString& ) const |
305 | { |
306 | |
307 | } |
308 | |
309 | KDateTable::KDateTable(const QDate& date_, QWidget* parent) |
310 | : QWidget(parent), d(new KDateTablePrivate(this)) |
311 | { |
312 | setFontSize(10); |
313 | setFocusPolicy(Qt::StrongFocus); |
314 | QPalette palette; |
315 | palette.setColor(backgroundRole(), KColorScheme(QPalette::Active, KColorScheme::View).background().color() ); |
316 | |
317 | setPalette(palette); |
318 | |
319 | if(!date_.isValid()) |
320 | { |
321 | kDebug(planDbg()) << "KDateTable ctor: WARNING: Given date is invalid, using current date." ; |
322 | setDate(QDate::currentDate()); // this initializes firstday, numdays, numDaysPrevMonth |
323 | } |
324 | else |
325 | setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth |
326 | initAccels(); |
327 | |
328 | init(); |
329 | } |
330 | |
331 | KDateTable::KDateTable(QWidget *parent) |
332 | : QWidget(parent), d(new KDateTablePrivate(this)) |
333 | { |
334 | setFontSize(10); |
335 | setFocusPolicy(Qt::StrongFocus); |
336 | QPalette palette; |
337 | palette.setColor(backgroundRole(), KColorScheme(QPalette::Active, KColorScheme::View).background().color() ); |
338 | setPalette(palette); |
339 | setDate(QDate::currentDate()); // this initializes firstday, numdays, numDaysPrevMonth |
340 | initAccels(); |
341 | |
342 | init(); |
343 | } |
344 | |
345 | KDateTable::~KDateTable() |
346 | { |
347 | delete d; |
348 | } |
349 | |
350 | void KDateTable::init() |
351 | { |
352 | d->m_dateDelegate = new KDateTableDateDelegate( this ); |
353 | d->m_weekDayDelegate = new KDateTableWeekDayDelegate( this ); |
354 | d->m_weekNumberDelegate = new KDateTableWeekNumberDelegate( this ); |
355 | |
356 | d->m_styleOptionDate.initFrom( this ); |
357 | d->m_styleOptionDate.displayAlignment = Qt::AlignCenter; |
358 | |
359 | d->m_styleOptionWeekDay.initFrom( this ); |
360 | d->m_styleOptionWeekDay.textAlignment = Qt::AlignCenter; |
361 | |
362 | d->m_styleOptionWeekNumber.initFrom( this ); |
363 | d->m_styleOptionWeekNumber.textAlignment = Qt::AlignCenter; |
364 | |
365 | //setModel( new KDateTableDataModel( this ) ); |
366 | } |
367 | |
368 | void KDateTable::setStyleOptionDate( const StyleOptionViewItem &so ) |
369 | { |
370 | d->m_styleOptionDate = so; |
371 | } |
372 | |
373 | void KDateTable::( const StyleOptionHeader &so ) |
374 | { |
375 | d->m_styleOptionWeekDay = so; |
376 | } |
377 | |
378 | void KDateTable::( const StyleOptionHeader &so ) |
379 | { |
380 | d->m_styleOptionWeekNumber = so; |
381 | } |
382 | |
383 | void KDateTable::slotReset() |
384 | { |
385 | update(); |
386 | } |
387 | |
388 | void KDateTable::slotDataChanged( const QDate &start, const QDate &end ) |
389 | { |
390 | Q_UNUSED(start); |
391 | Q_UNUSED(end); |
392 | update(); |
393 | } |
394 | |
395 | void KDateTable::setModel( KDateTableDataModel *model ) |
396 | { |
397 | if ( d->m_model ) |
398 | { |
399 | disconnect( d->m_model, SIGNAL( reset() ), this, SLOT( slotReset() ) ); |
400 | } |
401 | d->m_model = model; |
402 | if ( d->m_model ) |
403 | { |
404 | connect( d->m_model, SIGNAL( reset() ), this, SLOT( slotReset() ) ); |
405 | } |
406 | update(); |
407 | } |
408 | |
409 | KDateTableDataModel *KDateTable::model() const |
410 | { |
411 | return d->m_model; |
412 | } |
413 | |
414 | void KDateTable::setDateDelegate( KDateTableDateDelegate *delegate ) |
415 | { |
416 | delete d->m_dateDelegate; |
417 | d->m_dateDelegate = delegate; |
418 | } |
419 | |
420 | void KDateTable::setDateDelegate( const QDate &date, KDateTableDateDelegate *delegate ) |
421 | { |
422 | delete d->customPaintingModes.take( date.toString() ); |
423 | d->customPaintingModes[ date.toString() ] = delegate; |
424 | } |
425 | |
426 | void KDateTable::setWeekDayDelegate( KDateTableWeekDayDelegate *delegate ) |
427 | { |
428 | delete d->m_weekDayDelegate; |
429 | d->m_weekDayDelegate = delegate; |
430 | } |
431 | |
432 | void KDateTable::setWeekNumberDelegate( KDateTableWeekNumberDelegate *delegate ) |
433 | { |
434 | delete d->m_weekNumberDelegate; |
435 | d->m_weekNumberDelegate = delegate; |
436 | } |
437 | |
438 | void KDateTable::setWeekNumbersEnabled( bool enable ) |
439 | { |
440 | d->m_paintweeknumbers = enable; |
441 | } |
442 | |
443 | void KDateTable::setGridEnabled( bool enable ) |
444 | { |
445 | d->m_grid = enable; |
446 | } |
447 | |
448 | void KDateTable::initAccels() |
449 | { |
450 | KActionCollection* localCollection = new KActionCollection(this); |
451 | localCollection->addAssociatedWidget(this); |
452 | |
453 | QAction* next = localCollection->addAction(QLatin1String("next" )); |
454 | next->setShortcuts(KStandardShortcut::next()); |
455 | connect(next, SIGNAL(triggered(bool)), SLOT(nextMonth())); |
456 | |
457 | QAction* prior = localCollection->addAction(QLatin1String("prior" )); |
458 | prior->setShortcuts(KStandardShortcut::prior()); |
459 | connect(prior, SIGNAL(triggered(bool)), SLOT(previousMonth())); |
460 | |
461 | QAction* beginMonth = localCollection->addAction(QLatin1String("beginMonth" )); |
462 | beginMonth->setShortcuts(KStandardShortcut::home()); |
463 | connect(beginMonth, SIGNAL(triggered(bool)), SLOT(beginningOfMonth())); |
464 | |
465 | QAction* endMonth = localCollection->addAction(QLatin1String("endMonth" )); |
466 | endMonth->setShortcuts(KStandardShortcut::end()); |
467 | connect(endMonth, SIGNAL(triggered(bool)), SLOT(endOfMonth())); |
468 | |
469 | QAction* beginWeek = localCollection->addAction(QLatin1String("beginWeek" )); |
470 | beginWeek->setShortcuts(KStandardShortcut::beginningOfLine()); |
471 | connect(beginWeek, SIGNAL(triggered(bool)), SLOT(beginningOfWeek())); |
472 | |
473 | QAction* endWeek = localCollection->addAction("endWeek" ); |
474 | endWeek->setShortcuts(KStandardShortcut::endOfLine()); |
475 | connect(endWeek, SIGNAL(triggered(bool)), SLOT(endOfWeek())); |
476 | |
477 | localCollection->readSettings(); |
478 | } |
479 | |
480 | int KDateTable::posFromDate( const QDate &dt ) |
481 | { |
482 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
483 | |
484 | // ISO Week numbering always uses Monday as first day of week |
485 | const int firstWeekDay = (KGlobal::locale()->weekNumberSystem() == KLocale::IsoWeekNumber) |
486 | ? Qt::Monday |
487 | : KGlobal::locale()->weekStartDay(); |
488 | |
489 | int pos = calendar->day( dt ); |
490 | int offset = (d->firstday - firstWeekDay + 7) % 7; |
491 | // make sure at least one day of the previous month is visible. |
492 | // adjust this <1 if more days should be forced visible: |
493 | if ( offset < 1 ) offset += 7; |
494 | return pos + offset; |
495 | } |
496 | |
497 | QDate KDateTable::dateFromPos( int pos ) |
498 | { |
499 | QDate pCellDate; |
500 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
501 | calendar->setDate(pCellDate, calendar->year(d->mDate), calendar->month(d->mDate), 1); |
502 | |
503 | // ISO Week numbering always uses Monday as first day of week |
504 | const int firstWeekDay = (KGlobal::locale()->weekNumberSystem() == KLocale::IsoWeekNumber) |
505 | ? Qt::Monday |
506 | : KGlobal::locale()->weekStartDay(); |
507 | |
508 | int offset = (d->firstday - firstWeekDay + 7) % 7; |
509 | // make sure at least one day of the previous month is visible. |
510 | // adjust this <1 if more days should be forced visible: |
511 | if ( offset < 1 ) offset += 7; |
512 | pCellDate = calendar->addDays( pCellDate, pos - offset ); |
513 | return pCellDate; |
514 | } |
515 | |
516 | bool KDateTable::event( QEvent *event ) |
517 | { |
518 | if ( event->type() == QEvent::ToolTip ) { |
519 | //kDebug(planDbg())<<"Tooltip"; |
520 | QHelpEvent *e = static_cast<QHelpEvent*>( event ); |
521 | |
522 | double cellWidth = width() / ( d->m_paintweeknumbers ? 8.0 : 7.0 ); |
523 | double cellHeight = height() / 7.0; |
524 | int column = (int)floor(e->pos().x() / cellWidth); |
525 | int row = (int)floor(e->pos().y() / cellHeight); |
526 | QString text; |
527 | if ( row == 0 && column == 0 && d->m_paintweeknumbers ) { |
528 | // corner |
529 | } else if ( row == 0 ) { // we are drawing the headline (weekdays) |
530 | int col = d->m_paintweeknumbers ? column - 1 : column; |
531 | |
532 | // ISO Week numbering always uses Monday as first day of week |
533 | const int firstWeekDay = (KGlobal::locale()->weekNumberSystem() == KLocale::IsoWeekNumber) |
534 | ? Qt::Monday |
535 | : KGlobal::locale()->weekStartDay(); |
536 | |
537 | int day = ( col+firstWeekDay < 8 ) ? col+firstWeekDay : col+firstWeekDay-7; |
538 | if ( d->m_weekDayDelegate ) |
539 | { |
540 | text = d->m_weekDayDelegate->data( day, Qt::ToolTipRole, d->m_model ).toString(); |
541 | } |
542 | } |
543 | else if ( d->m_paintweeknumbers && column == 0 ) |
544 | { |
545 | int pos=7*(row-1); |
546 | QDate pCellDate = dateFromPos( pos ); |
547 | if ( d->m_weekNumberDelegate ) |
548 | { |
549 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
550 | #if KDE_IS_VERSION(4,7,0) |
551 | const int weekNumber = calendar->week( pCellDate ); |
552 | #else |
553 | const int weekNumber = calendar->weekNumber( pCellDate ); |
554 | #endif |
555 | text = d->m_weekNumberDelegate->data( weekNumber, Qt::ToolTipRole, d->m_model ).toString(); |
556 | } |
557 | } |
558 | else |
559 | { |
560 | // draw the dates |
561 | int col = d->m_paintweeknumbers ? column - 1 : column; |
562 | int pos=7*(row-1)+col; |
563 | QDate pCellDate = dateFromPos( pos ); |
564 | if ( d->m_dateDelegate ) { |
565 | text = d->m_dateDelegate->data( pCellDate, Qt::ToolTipRole, d->m_model ).toString(); |
566 | } |
567 | } |
568 | //kDebug(planDbg())<<row<<column<<text; |
569 | if ( text.isEmpty() ) { |
570 | QToolTip::hideText(); |
571 | } else { |
572 | QToolTip::showText( e->globalPos(), text ); |
573 | } |
574 | e->accept(); |
575 | return true; |
576 | } |
577 | return QWidget::event( event ); |
578 | } |
579 | |
580 | void KDateTable::paintEvent(QPaintEvent *e) |
581 | { |
582 | QPainter p(this); |
583 | const QRect &rectToUpdate = e->rect(); |
584 | double cellWidth = width() / ( d->m_paintweeknumbers ? 8.0 : 7.0 ); |
585 | double cellHeight = height() / 7.0; |
586 | int leftCol = (int)floor(rectToUpdate.left() / cellWidth); |
587 | int topRow = (int)floor(rectToUpdate.top() / cellHeight); |
588 | int rightCol = (int)ceil(rectToUpdate.right() / cellWidth); |
589 | int bottomRow = (int)ceil(rectToUpdate.bottom() / cellHeight); |
590 | bottomRow = qMin(bottomRow, 6); |
591 | rightCol = qMin(rightCol, ( d->m_paintweeknumbers ? 7 : 6 ) ); |
592 | p.translate(leftCol * cellWidth, topRow * cellHeight); |
593 | for (int i = leftCol; i <= rightCol; ++i) { |
594 | for (int j = topRow; j <= bottomRow; ++j) { |
595 | paintCell(&p, j, i); |
596 | p.translate(0, cellHeight); |
597 | } |
598 | |
599 | p.translate(cellWidth, 0); |
600 | p.translate(0, -cellHeight * (bottomRow - topRow + 1)); |
601 | } |
602 | } |
603 | |
604 | void |
605 | KDateTable::paintCell(QPainter *painter, int row, int column) |
606 | { |
607 | //kDebug(planDbg()); |
608 | |
609 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
610 | |
611 | QSizeF size; |
612 | QString text; |
613 | QPen pen; |
614 | double w = width() / ( d->m_paintweeknumbers ? 8.0 : 7.0 ); |
615 | double h = height() / 7.0; |
616 | w -= 1; |
617 | h -= 1; |
618 | QRectF rect( 0, 0, w, h ); |
619 | if ( row == 0 && column == 0 && d->m_paintweeknumbers ) |
620 | { |
621 | // paint something in the corner?? |
622 | /* painter->setPen(palette().color(QPalette::Text)); |
623 | painter->drawRect( rect );*/ |
624 | return; |
625 | } |
626 | if ( row == 0 ) |
627 | { // we are drawing the headline (weekdays) |
628 | d->m_styleOptionWeekDay.rectF = rect; |
629 | d->m_styleOptionWeekDay.state = QStyle::State_None; |
630 | |
631 | int col = d->m_paintweeknumbers ? column - 1 : column; |
632 | |
633 | // ISO Week numbering always uses Monday as first day of week |
634 | const int firstWeekDay = (KGlobal::locale()->weekNumberSystem() == KLocale::IsoWeekNumber) |
635 | ? Qt::Monday |
636 | : KGlobal::locale()->weekStartDay(); |
637 | |
638 | int day = ( col+firstWeekDay < 8 ) ? col+firstWeekDay : col+firstWeekDay-7; |
639 | if ( d->m_weekDayDelegate ) |
640 | { |
641 | size = d->m_weekDayDelegate->paint( painter, d->m_styleOptionWeekDay, day, d->m_model ).size(); |
642 | } |
643 | } |
644 | else if ( d->m_paintweeknumbers && column == 0 ) |
645 | { |
646 | d->m_styleOptionWeekNumber.rectF = rect; |
647 | d->m_styleOptionWeekNumber.state = QStyle::State_None; |
648 | |
649 | int pos=7*(row-1); |
650 | QDate pCellDate = dateFromPos( pos ); |
651 | if ( d->m_weekNumberDelegate ) |
652 | { |
653 | #if KDE_IS_VERSION(4,7,0) |
654 | const int weekNumber = calendar->week( pCellDate ); |
655 | #else |
656 | const int weekNumber = calendar->weekNumber( pCellDate ); |
657 | #endif |
658 | size = d->m_weekNumberDelegate->paint( painter, d->m_styleOptionWeekNumber, weekNumber, d->m_model ).size(); |
659 | } |
660 | } |
661 | else |
662 | { |
663 | // draw the dates |
664 | int col = d->m_paintweeknumbers ? column - 1 : column; |
665 | int pos=7*(row-1)+col; |
666 | |
667 | if ( d->m_grid ) |
668 | { |
669 | painter->save(); |
670 | QPen pen( "lightgrey" ); |
671 | pen.setWidthF( 0.5 ); |
672 | painter->setPen( pen ); |
673 | double pw = painter->pen().width(); |
674 | if ( col > 0 ) |
675 | { |
676 | painter->drawLine( rect.topLeft(), rect.bottomLeft() ); |
677 | } |
678 | if ( row > 1 ) |
679 | { |
680 | painter->drawLine( rect.topLeft(), rect.topRight() ); |
681 | } |
682 | rect = rect.adjusted(pw, pw, 0, 0 ); |
683 | painter->restore(); |
684 | //kDebug(planDbg())<<d->m_grid<<" "<<pw<<" "<<rect; |
685 | } |
686 | |
687 | d->m_styleOptionDate.rectF = rect; |
688 | d->m_styleOptionDate.state = QStyle::State_None; |
689 | |
690 | |
691 | QDate pCellDate = dateFromPos( pos ); |
692 | if( calendar->month(pCellDate) == calendar->month(d->mDate) ) |
693 | { |
694 | d->m_styleOptionDate.state |= QStyle::State_Active; |
695 | } |
696 | if ( d->m_selectedDates.contains( pCellDate ) ) |
697 | { |
698 | d->m_styleOptionDate.state |= QStyle::State_Selected; |
699 | } |
700 | if ( isEnabled() ) |
701 | { |
702 | d->m_styleOptionDate.state |= QStyle::State_Enabled; |
703 | } |
704 | if ( pCellDate == d->mDate ) |
705 | { |
706 | d->m_styleOptionDate.state |= QStyle::State_Active; |
707 | if ( d->m_selectionmode != SingleSelection && hasFocus() ) |
708 | { |
709 | d->m_styleOptionDate.state |= QStyle::State_HasFocus; |
710 | } |
711 | } |
712 | KDateTableDateDelegate *del = d->customPaintingModes.value( pCellDate.toString() ); |
713 | if ( del == 0 ) { |
714 | del = d->m_dateDelegate; |
715 | } |
716 | if ( del ) { |
717 | //kDebug(planDbg())<<del; |
718 | size = del->paint( painter, d->m_styleOptionDate, pCellDate, d->m_model ).size(); |
719 | } else kWarning()<<"No delegate!" ; |
720 | } |
721 | if(size.width() > d->maxCell.width()) d->maxCell.setWidth(size.width()); |
722 | if(size.height() > d->maxCell.height()) d->maxCell.setHeight(size.height()); |
723 | } |
724 | |
725 | void KDateTable::KDateTablePrivate::nextMonth() |
726 | { |
727 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
728 | q->setDate(calendar->addMonths( mDate, 1 )); |
729 | } |
730 | |
731 | void KDateTable::KDateTablePrivate::previousMonth() |
732 | { |
733 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
734 | q->setDate(calendar->addMonths( mDate, -1 )); |
735 | } |
736 | |
737 | void KDateTable::KDateTablePrivate::beginningOfMonth() |
738 | { |
739 | q->setDate(mDate.addDays(1 - mDate.day())); |
740 | } |
741 | |
742 | void KDateTable::KDateTablePrivate::endOfMonth() |
743 | { |
744 | q->setDate(mDate.addDays(mDate.daysInMonth() - mDate.day())); |
745 | } |
746 | |
747 | void KDateTable::KDateTablePrivate::beginningOfWeek() |
748 | { |
749 | q->setDate(mDate.addDays(1 - mDate.dayOfWeek())); |
750 | } |
751 | |
752 | void KDateTable::KDateTablePrivate::endOfWeek() |
753 | { |
754 | q->setDate(mDate.addDays(7 - mDate.dayOfWeek())); |
755 | } |
756 | |
757 | void |
758 | KDateTable::keyPressEvent( QKeyEvent *e ) |
759 | { |
760 | QDate cd = d->mDate; |
761 | switch( e->key() ) { |
762 | case Qt::Key_Up: |
763 | setDate(d->mDate.addDays(-7)); |
764 | break; |
765 | case Qt::Key_Down: |
766 | setDate(d->mDate.addDays(7)); |
767 | break; |
768 | case Qt::Key_Left: |
769 | setDate(d->mDate.addDays(-1)); |
770 | break; |
771 | case Qt::Key_Right: |
772 | setDate(d->mDate.addDays(1)); |
773 | break; |
774 | case Qt::Key_Minus: |
775 | setDate(d->mDate.addDays(-1)); |
776 | break; |
777 | case Qt::Key_Plus: |
778 | setDate(d->mDate.addDays(1)); |
779 | break; |
780 | case Qt::Key_N: |
781 | setDate(QDate::currentDate()); |
782 | break; |
783 | case Qt::Key_Return: |
784 | case Qt::Key_Enter: |
785 | emit tableClicked(); |
786 | break; |
787 | } |
788 | |
789 | switch( e->key() ) { |
790 | case Qt::Key_Down: |
791 | case Qt::Key_Up: |
792 | case Qt::Key_Left: |
793 | case Qt::Key_Right: |
794 | case Qt::Key_Minus: |
795 | case Qt::Key_Plus: { |
796 | if ( d->m_selectionmode == ExtendedSelection ) { |
797 | if ( e->modifiers() & Qt::ShiftModifier ) { |
798 | int inc = cd > d->mDate ? 1 : -1; |
799 | for ( QDate dd = d->mDate; dd != cd; dd = dd.addDays( inc ) ) { |
800 | if ( ! d->m_selectedDates.contains( dd ) ) { |
801 | d->m_selectedDates << dd; |
802 | } |
803 | } |
804 | } else if ( e->modifiers() & Qt::ControlModifier ) { |
805 | // keep selection, just move on |
806 | } else { |
807 | d->m_selectedDates.clear(); |
808 | } |
809 | } |
810 | break;} |
811 | case Qt::Key_Space: |
812 | case Qt::Key_Select: |
813 | if ( d->m_selectionmode == ExtendedSelection ) { |
814 | if ( e->modifiers() & Qt::ControlModifier ) { |
815 | if ( d->m_selectedDates.contains( d->mDate ) ) { |
816 | d->m_selectedDates.removeAt( d->m_selectedDates.indexOf( d->mDate ) ); |
817 | } else { |
818 | d->m_selectedDates << d->mDate; |
819 | } |
820 | } else if ( ! d->m_selectedDates.contains( d->mDate ) ) { |
821 | d->m_selectedDates << d->mDate; |
822 | } |
823 | update(); |
824 | } |
825 | break; |
826 | case Qt::Key_Menu: |
827 | if ( d->popupMenuEnabled ) |
828 | { |
829 | KMenu * = new KMenu(); |
830 | if ( d->m_selectionmode == ExtendedSelection ) { |
831 | emit aboutToShowContextMenu( menu, d->m_selectedDates ); |
832 | } else { |
833 | menu->addTitle( KGlobal::locale()->formatDate(d->mDate) ); |
834 | emit aboutToShowContextMenu( menu, d->mDate ); |
835 | } |
836 | if ( menu->isEmpty() ) { |
837 | delete menu; |
838 | } else { |
839 | int p = posFromDate( d->mDate ) - 1; |
840 | int col = p % 7; |
841 | int row = p / 7; |
842 | QPoint pos = geometry().topLeft(); |
843 | QSize size = geometry().size(); |
844 | int sx = size.width() / 8; |
845 | int sy = size.height() / 7; |
846 | pos = QPoint( pos.x() + sx + sx / 2 + sx * col, pos.y() + sy + sy * row ); |
847 | kDebug(planDbg())<<pos<<p<<col<<row; |
848 | menu->popup(mapToGlobal(pos)); |
849 | } |
850 | } |
851 | break; |
852 | case Qt::Key_Control: |
853 | case Qt::Key_Alt: |
854 | case Qt::Key_Meta: |
855 | case Qt::Key_Shift: |
856 | // Don't beep for modifiers |
857 | break; |
858 | default: |
859 | if (!e->modifiers()) { // hm |
860 | KNotification::beep(); |
861 | } |
862 | } |
863 | } |
864 | |
865 | void |
866 | KDateTable::setFontSize(int size) |
867 | { |
868 | int count; |
869 | QFontMetricsF metrics(fontMetrics()); |
870 | QRectF rect; |
871 | // ----- store rectangles: |
872 | d->fontsize=size; |
873 | // ----- find largest day name: |
874 | d->maxCell.setWidth(0); |
875 | d->maxCell.setHeight(0); |
876 | for(count=0; count<7; ++count) |
877 | { |
878 | rect=metrics.boundingRect(KGlobal::locale()->calendar() |
879 | ->weekDayName(count+1, KCalendarSystem::ShortDayName)); |
880 | d->maxCell.setWidth(qMax(d->maxCell.width(), rect.width())); |
881 | d->maxCell.setHeight(qMax(d->maxCell.height(), rect.height())); |
882 | } |
883 | // ----- compare with a real wide number and add some space: |
884 | rect=metrics.boundingRect(QLatin1String("88" )); |
885 | d->maxCell.setWidth(qMax(d->maxCell.width()+2, rect.width())); |
886 | d->maxCell.setHeight(qMax(d->maxCell.height()+4, rect.height())); |
887 | } |
888 | |
889 | void |
890 | KDateTable::wheelEvent ( QWheelEvent * e ) |
891 | { |
892 | setDate(d->mDate.addMonths( -(int)(e->delta()/120)) ); |
893 | e->accept(); |
894 | } |
895 | |
896 | void |
897 | KDateTable::mousePressEvent(QMouseEvent *e) |
898 | { |
899 | if(e->type()!=QEvent::MouseButtonPress) |
900 | { // the KDatePicker only reacts on mouse press events: |
901 | return; |
902 | } |
903 | if(!isEnabled()) |
904 | { |
905 | KNotification::beep(); |
906 | return; |
907 | } |
908 | |
909 | // ----- |
910 | int row, col, pos; |
911 | QPoint mouseCoord; |
912 | // ----- |
913 | mouseCoord = e->pos(); |
914 | row=mouseCoord.y() / ( height() / 7 ); |
915 | col=mouseCoord.x() / ( width() / ( d->m_paintweeknumbers ? 8 : 7 ) ); |
916 | //kDebug(planDbg())<<d->maxCell<<", "<<size()<<row<<", "<<col<<", "<<mouseCoord; |
917 | if(row<1 ) |
918 | { // the user clicked on the frame of the table |
919 | //kDebug(planDbg())<<"weekday "<<col; |
920 | return; |
921 | } |
922 | if ( col < ( d->m_paintweeknumbers ? 1 : 0 ) ) |
923 | { |
924 | //kDebug(planDbg())<<"weeknumber "<<row; |
925 | return; |
926 | } |
927 | if ( d->m_paintweeknumbers ) { |
928 | --col; |
929 | } |
930 | |
931 | // Rows and columns are zero indexed. The (row - 1) below is to avoid counting |
932 | // the row with the days of the week in the calculation. |
933 | |
934 | // old selected date: |
935 | // new position and date |
936 | pos = (7 * (row - 1)) + col; |
937 | QDate clickedDate = dateFromPos( pos ); |
938 | |
939 | if ( d->m_selectionmode != ExtendedSelection || e->button() != Qt::RightButton || ! d->m_selectedDates.contains( clickedDate ) ) |
940 | { |
941 | switch ( d->m_selectionmode ) |
942 | { |
943 | case SingleSelection: |
944 | break; |
945 | case ExtendedSelection: |
946 | //kDebug(planDbg())<<"extended "<<e->modifiers()<<", "<<clickedDate; |
947 | if ( e->modifiers() & Qt::ShiftModifier ) |
948 | { |
949 | if ( d->m_selectedDates.isEmpty() ) |
950 | { |
951 | d->m_selectedDates << clickedDate; |
952 | } |
953 | else if ( d->mDate != clickedDate ) |
954 | { |
955 | QDate dt = d->mDate; |
956 | int nxt = dt < clickedDate ? 1 : -1; |
957 | if ( d->m_selectedDates.contains( clickedDate ) ) |
958 | { |
959 | d->m_selectedDates.removeAt( d->m_selectedDates.indexOf( clickedDate ) ); |
960 | } |
961 | while ( dt != clickedDate ) |
962 | { |
963 | if ( ! d->m_selectedDates.contains( dt ) ) |
964 | { |
965 | d->m_selectedDates << dt; |
966 | } |
967 | dt = dt.addDays( nxt ); |
968 | } |
969 | d->m_selectedDates << clickedDate; |
970 | } |
971 | else |
972 | { |
973 | break; // selection not changed |
974 | } |
975 | } |
976 | else if ( e->modifiers() & Qt::ControlModifier ) |
977 | { |
978 | if ( d->m_selectedDates.contains( clickedDate ) ) |
979 | { |
980 | d->m_selectedDates.removeAt( d->m_selectedDates.indexOf( clickedDate ) ); |
981 | } |
982 | else |
983 | { |
984 | d->m_selectedDates << clickedDate; |
985 | } |
986 | } |
987 | else |
988 | { |
989 | d->m_selectedDates.clear(); |
990 | d->m_selectedDates << clickedDate; |
991 | } |
992 | emit selectionChanged( d->m_selectedDates ); |
993 | break; |
994 | default: break; |
995 | } |
996 | // set the new date. If it is in the previous or next month, the month will |
997 | // automatically be changed, no need to do that manually... |
998 | setDate( clickedDate ); |
999 | |
1000 | // This could be optimized to only call update over the regions |
1001 | // of old and new cell, but 99% of times there is also a call to |
1002 | // setDate that already calls update() so no need to optimize that |
1003 | // much here |
1004 | update(); |
1005 | } |
1006 | emit tableClicked(); |
1007 | |
1008 | if ( e->button() == Qt::RightButton && d->popupMenuEnabled ) |
1009 | { |
1010 | KMenu * = new KMenu(); |
1011 | if ( d->m_selectionmode == ExtendedSelection ) { |
1012 | emit aboutToShowContextMenu( menu, d->m_selectedDates ); |
1013 | } else { |
1014 | menu->addTitle( KGlobal::locale()->formatDate(clickedDate) ); |
1015 | emit aboutToShowContextMenu( menu, clickedDate ); |
1016 | } |
1017 | menu->popup(e->globalPos()); |
1018 | } |
1019 | } |
1020 | |
1021 | bool |
1022 | KDateTable::setDate(const QDate& date_) |
1023 | { |
1024 | bool changed=false; |
1025 | QDate temp; |
1026 | // ----- |
1027 | if(!date_.isValid()) |
1028 | { |
1029 | kDebug(planDbg()) << "KDateTable::setDate: refusing to set invalid date." ; |
1030 | return false; |
1031 | } |
1032 | if(d->mDate!=date_) |
1033 | { |
1034 | emit(dateChanged(d->mDate, date_)); |
1035 | d->mDate=date_; |
1036 | emit(dateChanged(d->mDate)); |
1037 | changed=true; |
1038 | } |
1039 | if ( d->m_selectionmode == KDateTable::SingleSelection ) |
1040 | { |
1041 | d->m_selectedDates.clear(); |
1042 | d->m_selectedDates << date_; |
1043 | emit selectionChanged( d->m_selectedDates ); |
1044 | } |
1045 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
1046 | |
1047 | calendar->setDate(temp, calendar->year(d->mDate), calendar->month(d->mDate), 1); |
1048 | //temp.setDate(d->mDate.year(), d->mDate.month(), 1); |
1049 | //kDebug(planDbg()) << "firstDayInWeek: " << temp.toString(); |
1050 | d->firstday=temp.dayOfWeek(); |
1051 | d->numdays=calendar->daysInMonth(d->mDate); |
1052 | |
1053 | temp = calendar->addMonths(temp, -1); |
1054 | d->numDaysPrevMonth=calendar->daysInMonth(temp); |
1055 | if(changed) |
1056 | { |
1057 | update(); |
1058 | } |
1059 | return true; |
1060 | } |
1061 | |
1062 | const QDate& |
1063 | KDateTable::date() const |
1064 | { |
1065 | return d->mDate; |
1066 | } |
1067 | |
1068 | // what are those repaintContents() good for? (pfeiffer) |
1069 | void KDateTable::focusInEvent( QFocusEvent *e ) |
1070 | { |
1071 | // repaintContents(false); |
1072 | QWidget::focusInEvent( e ); |
1073 | emit focusChanged( e ); |
1074 | } |
1075 | |
1076 | void KDateTable::focusOutEvent( QFocusEvent *e ) |
1077 | { |
1078 | // repaintContents(false); |
1079 | QWidget::focusOutEvent( e ); |
1080 | emit focusChanged( e ); |
1081 | } |
1082 | |
1083 | QSize |
1084 | KDateTable::sizeHint() const |
1085 | { |
1086 | if(d->maxCell.height()>0 && d->maxCell.width()>0) |
1087 | { |
1088 | int s = d->m_paintweeknumbers ? 8 : 7; |
1089 | return QSize(qRound(d->maxCell.width()*s), |
1090 | (qRound(d->maxCell.height()+2)*7)); |
1091 | } else { |
1092 | kDebug(planDbg()) << "KDateTable::sizeHint: obscure failure - " ; |
1093 | return QSize(-1, -1); |
1094 | } |
1095 | } |
1096 | |
1097 | void KDateTable::( bool enable ) |
1098 | { |
1099 | d->popupMenuEnabled=enable; |
1100 | } |
1101 | |
1102 | bool KDateTable::() const |
1103 | { |
1104 | return d->popupMenuEnabled; |
1105 | } |
1106 | |
1107 | void KDateTable::setCustomDatePainting(const QDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor) |
1108 | { |
1109 | KDateTableCustomDateDelegate *del = new KDateTableCustomDateDelegate(); |
1110 | del->fgColor = fgColor; |
1111 | del->bgMode = bgMode; |
1112 | del->bgColor = bgColor; |
1113 | setDateDelegate( date, del ); |
1114 | update(); |
1115 | } |
1116 | |
1117 | void KDateTable::unsetCustomDatePainting( const QDate &date ) |
1118 | { |
1119 | d->customPaintingModes.remove( date.toString() ); |
1120 | } |
1121 | |
1122 | void KDateTable::setSelectionMode( SelectionMode mode ) |
1123 | { |
1124 | d->m_selectionmode = mode; |
1125 | } |
1126 | |
1127 | KDateInternalYearSelector::KDateInternalYearSelector |
1128 | (QWidget* parent) |
1129 | : QLineEdit(parent), |
1130 | val(new QIntValidator(this)), |
1131 | result(0) |
1132 | { |
1133 | QFont font; |
1134 | // ----- |
1135 | font=KGlobalSettings::generalFont(); |
1136 | setFont(font); |
1137 | setFrame(false); |
1138 | // we have to respect the limits of QDate here, I fear: |
1139 | val->setRange(0, 8000); |
1140 | setValidator(val); |
1141 | connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot())); |
1142 | } |
1143 | |
1144 | void KDateInternalYearSelector::focusOutEvent(QFocusEvent*) |
1145 | { |
1146 | emit(closeMe(1)); |
1147 | } |
1148 | |
1149 | void |
1150 | KDateInternalYearSelector::yearEnteredSlot() |
1151 | { |
1152 | bool ok; |
1153 | int year; |
1154 | QDate date; |
1155 | // ----- check if this is a valid year: |
1156 | year=text().toInt(&ok); |
1157 | if(!ok) |
1158 | { |
1159 | KNotification::beep(); |
1160 | return; |
1161 | } |
1162 | //date.setDate(year, 1, 1); |
1163 | KGlobal::locale()->calendar()->setDate(date, year, 1, 1); |
1164 | if(!date.isValid()) |
1165 | { |
1166 | KNotification::beep(); |
1167 | return; |
1168 | } |
1169 | result=year; |
1170 | emit(closeMe(1)); |
1171 | } |
1172 | |
1173 | int |
1174 | KDateInternalYearSelector::getYear() |
1175 | { |
1176 | return result; |
1177 | } |
1178 | |
1179 | void |
1180 | KDateInternalYearSelector::setYear(int year) |
1181 | { |
1182 | QString temp; |
1183 | // ----- |
1184 | temp.setNum(year); |
1185 | setText(temp); |
1186 | } |
1187 | |
1188 | KPopupFrame::(QWidget* parent) |
1189 | : QFrame(parent, Qt::Popup), d(new KPopupFramePrivate(this)) |
1190 | { |
1191 | setFrameStyle(QFrame::Box|QFrame::Raised); |
1192 | setMidLineWidth(2); |
1193 | } |
1194 | |
1195 | KPopupFrame::() |
1196 | { |
1197 | delete d; |
1198 | } |
1199 | |
1200 | void |
1201 | KPopupFrame::(QKeyEvent* e) |
1202 | { |
1203 | if(e->key()==Qt::Key_Escape) |
1204 | { |
1205 | d->result=0; // rejected |
1206 | emit leaveModality(); |
1207 | //qApp->exit_loop(); |
1208 | } |
1209 | } |
1210 | |
1211 | void |
1212 | KPopupFrame::(int r) |
1213 | { |
1214 | d->result=r; |
1215 | emit leaveModality(); |
1216 | //qApp->exit_loop(); |
1217 | } |
1218 | |
1219 | void |
1220 | KPopupFrame::setMainWidget(QWidget* m) |
1221 | { |
1222 | d->main=m; |
1223 | if(d->main) |
1224 | { |
1225 | resize(d->main->width()+2*frameWidth(), d->main->height()+2*frameWidth()); |
1226 | } |
1227 | } |
1228 | |
1229 | void |
1230 | KPopupFrame::(QResizeEvent*) |
1231 | { |
1232 | if(d->main) |
1233 | { |
1234 | d->main->setGeometry(frameWidth(), frameWidth(), |
1235 | width()-2*frameWidth(), height()-2*frameWidth()); |
1236 | } |
1237 | } |
1238 | |
1239 | void |
1240 | KPopupFrame::(const QPoint &pos) |
1241 | { |
1242 | // Make sure the whole popup is visible. |
1243 | QRect d = KGlobalSettings::desktopGeometry(pos); |
1244 | |
1245 | int x = pos.x(); |
1246 | int y = pos.y(); |
1247 | int w = width(); |
1248 | int h = height(); |
1249 | if (x+w > d.x()+d.width()) |
1250 | x = d.width() - w; |
1251 | if (y+h > d.y()+d.height()) |
1252 | y = d.height() - h; |
1253 | if (x < d.x()) |
1254 | x = 0; |
1255 | if (y < d.y()) |
1256 | y = 0; |
1257 | |
1258 | // Pop the thingy up. |
1259 | move(x, y); |
1260 | show(); |
1261 | } |
1262 | |
1263 | int |
1264 | KPopupFrame::(const QPoint &pos) |
1265 | { |
1266 | popup(pos); |
1267 | repaint(); |
1268 | QEventLoop eventLoop; |
1269 | connect(this, SIGNAL(leaveModality()), |
1270 | &eventLoop, SLOT(quit())); |
1271 | eventLoop.exec(); |
1272 | |
1273 | hide(); |
1274 | kDebug(planDbg())<<d->result; |
1275 | return d->result; |
1276 | } |
1277 | |
1278 | int |
1279 | KPopupFrame::(int x, int y) |
1280 | { |
1281 | return exec(QPoint(x, y)); |
1282 | } |
1283 | |
1284 | //----------------------- |
1285 | KDateTableDataModel::KDateTableDataModel( QObject *parent ) |
1286 | : QObject( parent ) |
1287 | { |
1288 | } |
1289 | |
1290 | KDateTableDataModel::~KDateTableDataModel() |
1291 | { |
1292 | } |
1293 | |
1294 | QVariant KDateTableDataModel::data( const QDate &date, int role, int dataType ) const |
1295 | { |
1296 | Q_UNUSED(date); |
1297 | Q_UNUSED(role); |
1298 | Q_UNUSED(dataType); |
1299 | return QVariant(); |
1300 | } |
1301 | |
1302 | QVariant KDateTableDataModel::weekDayData( int day, int role ) const |
1303 | { |
1304 | Q_UNUSED(day); |
1305 | Q_UNUSED(role); |
1306 | return QVariant(); |
1307 | } |
1308 | |
1309 | QVariant KDateTableDataModel::weekNumberData( int week, int role ) const |
1310 | { |
1311 | Q_UNUSED(week); |
1312 | Q_UNUSED(role); |
1313 | return QVariant(); |
1314 | } |
1315 | |
1316 | //------------- |
1317 | KDateTableDateDelegate::KDateTableDateDelegate( QObject *parent ) |
1318 | : QObject( parent ) |
1319 | { |
1320 | } |
1321 | |
1322 | QVariant KDateTableDateDelegate::data( const QDate &date, int role, KDateTableDataModel *model ) |
1323 | { |
1324 | //kDebug(planDbg())<<date<<role<<model; |
1325 | if ( model == 0 ) { |
1326 | return QVariant(); |
1327 | } |
1328 | return model->data( date, role ); |
1329 | } |
1330 | |
1331 | QRectF KDateTableDateDelegate::paint( QPainter *painter, const StyleOptionViewItem &option, const QDate &date, KDateTableDataModel *model ) |
1332 | { |
1333 | //kDebug(planDbg())<<date; |
1334 | painter->save(); |
1335 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
1336 | QRectF r; |
1337 | |
1338 | QPalette palette = option.palette; |
1339 | if ( option.state & QStyle::State_Enabled && option.state & QStyle::State_Active ) { |
1340 | palette.setCurrentColorGroup( QPalette::Active ); |
1341 | } else { |
1342 | palette.setCurrentColorGroup( QPalette::Inactive ); |
1343 | } |
1344 | |
1345 | QFont font = option.font; |
1346 | QColor textColor = palette.text().color(); |
1347 | QBrush bg( palette.base() ); |
1348 | Qt::Alignment align = option.displayAlignment; |
1349 | QString text = calendar->formatDate(date, KLocale::Day, KLocale::ShortNumber); |
1350 | |
1351 | if ( model ) |
1352 | { |
1353 | QVariant v = model->data( date, Qt::ForegroundRole ); |
1354 | if ( v.isValid() ) |
1355 | { |
1356 | textColor = v.value<QColor>(); |
1357 | } |
1358 | v = model->data( date, Qt::BackgroundRole ); |
1359 | if ( v.isValid() ) |
1360 | { |
1361 | bg.setColor( v.value<QColor>() ); |
1362 | } |
1363 | v = model->data( date ); |
1364 | if ( v.isValid() ) |
1365 | { |
1366 | text = v.toString(); |
1367 | } |
1368 | v = model->data( date, Qt::TextAlignmentRole ); |
1369 | if ( v.isValid() ) |
1370 | { |
1371 | align = (Qt::Alignment)v.toInt(); |
1372 | } |
1373 | v = model->data( date, Qt::FontRole ); |
1374 | if ( v.isValid() ) |
1375 | { |
1376 | font = v.value<QFont>(); |
1377 | } |
1378 | } |
1379 | |
1380 | QPen pen = painter->pen(); |
1381 | pen.setColor( textColor ); |
1382 | |
1383 | if ( option.state & QStyle::State_Selected ) { |
1384 | bg = palette.highlight(); |
1385 | } |
1386 | painter->fillRect( option.rectF, bg ); |
1387 | painter->setBrush( bg ); |
1388 | |
1389 | |
1390 | if ( option.state & QStyle::State_HasFocus ) { |
1391 | painter->setPen( palette.text().color() ); |
1392 | painter->setPen( Qt::DotLine ); |
1393 | painter->drawRect( option.rectF ); |
1394 | } else if ( date == QDate::currentDate() ) { |
1395 | painter->setPen( palette.text().color() ); |
1396 | painter->drawRect( option.rectF ); |
1397 | } |
1398 | |
1399 | if ( option.state & QStyle::State_Selected ) { |
1400 | pen.setColor( palette.highlightedText().color() ); |
1401 | } |
1402 | painter->setFont( font ); |
1403 | painter->setPen( pen ); |
1404 | painter->drawText( option.rectF, align, text, &r ); |
1405 | |
1406 | painter->restore(); |
1407 | return r; |
1408 | } |
1409 | |
1410 | //--------- |
1411 | |
1412 | KDateTableCustomDateDelegate::KDateTableCustomDateDelegate( QObject *parent ) |
1413 | : KDateTableDateDelegate( parent ) |
1414 | { |
1415 | } |
1416 | |
1417 | QRectF KDateTableCustomDateDelegate::paint( QPainter *painter, const StyleOptionViewItem &option, const QDate &date, KDateTableDataModel *model ) |
1418 | { |
1419 | //kDebug(planDbg())<<date; |
1420 | painter->save(); |
1421 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
1422 | QRectF r; |
1423 | bool paintRect=true; |
1424 | QBrush bg(option.palette.base()); |
1425 | |
1426 | if( (option.state & QStyle::State_Active) == 0 ) |
1427 | { // we are either |
1428 | // ° painting a day of the previous month or |
1429 | // ° painting a day of the following month |
1430 | // TODO: don't hardcode gray here! Use a color with less contrast to the background than normal text. |
1431 | painter->setPen( option.palette.color(QPalette::Mid) ); |
1432 | // painter->setPen(gray); |
1433 | } |
1434 | else |
1435 | { // paint a day of the current month |
1436 | if (bgMode != KDateTable::NoBgMode) |
1437 | { |
1438 | QBrush oldbrush=painter->brush(); |
1439 | painter->setBrush( bgColor ); |
1440 | switch(bgMode) |
1441 | { |
1442 | case(KDateTable::CircleMode) : painter->drawEllipse(option.rectF);break; |
1443 | case(KDateTable::RectangleMode) : painter->drawRect(option.rectF);break; |
1444 | case(KDateTable::NoBgMode) : // Should never be here, but just to get one |
1445 | // less warning when compiling |
1446 | default: break; |
1447 | } |
1448 | painter->setBrush( oldbrush ); |
1449 | paintRect=false; |
1450 | } |
1451 | painter->setPen( fgColor ); |
1452 | |
1453 | QPen pen=painter->pen(); |
1454 | if ( option.state & QStyle::State_Selected ) |
1455 | { |
1456 | // draw the currently selected date |
1457 | //kDebug(planDbg())<<"selected: "<<date; |
1458 | if ( option.state & QStyle::State_Enabled ) |
1459 | { |
1460 | //kDebug(planDbg())<<"enabled & selected: "<<date; |
1461 | painter->setPen(option.palette.color(QPalette::Highlight)); |
1462 | painter->setBrush(option.palette.color(QPalette::Highlight)); |
1463 | } |
1464 | else |
1465 | { |
1466 | //kDebug(planDbg())<<"disabled & selected: "<<date; |
1467 | painter->setPen(option.palette.color(QPalette::Text)); |
1468 | painter->setBrush(option.palette.color(QPalette::Text)); |
1469 | } |
1470 | pen=option.palette.color(QPalette::HighlightedText); |
1471 | } |
1472 | else |
1473 | { |
1474 | painter->setBrush(option.palette.color(QPalette::Background)); |
1475 | painter->setPen(option.palette.color(QPalette::Background)); |
1476 | } |
1477 | |
1478 | if ( date == QDate::currentDate() ) |
1479 | { |
1480 | painter->setPen(option.palette.color(QPalette::Text)); |
1481 | } |
1482 | |
1483 | if ( paintRect ) |
1484 | { |
1485 | painter->drawRect(option.rectF); |
1486 | } |
1487 | painter->setPen(pen); |
1488 | QString text = calendar->formatDate(date, KLocale::Day, KLocale::ShortNumber); |
1489 | if ( model ) |
1490 | { |
1491 | QVariant v = model->data( date ); |
1492 | if ( v.isValid() ) |
1493 | { |
1494 | text = v.toString(); |
1495 | } |
1496 | } |
1497 | painter->drawText(option.rectF, Qt::AlignCenter, text, &r); |
1498 | } |
1499 | painter->restore(); |
1500 | return r; |
1501 | } |
1502 | |
1503 | //--------- |
1504 | KDateTableWeekDayDelegate::KDateTableWeekDayDelegate( QObject *parent ) |
1505 | : QObject( parent ) |
1506 | { |
1507 | } |
1508 | |
1509 | QVariant KDateTableWeekDayDelegate::data( int day, int role, KDateTableDataModel *model ) |
1510 | { |
1511 | //kDebug(planDbg())<<day<<role<<model; |
1512 | if ( model == 0 ) { |
1513 | return QVariant(); |
1514 | } |
1515 | return model->weekDayData( day, role ); |
1516 | } |
1517 | |
1518 | QRectF KDateTableWeekDayDelegate::( QPainter *painter, const StyleOptionHeader &option, int daynum, KDateTableDataModel *model ) |
1519 | { |
1520 | //kDebug(planDbg())<<daynum; |
1521 | painter->save(); |
1522 | const KCalendarSystem * calendar = KGlobal::locale()->calendar(); |
1523 | |
1524 | QPalette palette = option.palette; |
1525 | if ( option.state & QStyle::State_Active ) { |
1526 | palette.setCurrentColorGroup( QPalette::Active ); |
1527 | } else { |
1528 | palette.setCurrentColorGroup( QPalette::Inactive ); |
1529 | } |
1530 | QRectF rect; |
1531 | QFont font = KGlobalSettings::generalFont(); |
1532 | // font.setBold(true); |
1533 | painter->setFont(font); |
1534 | |
1535 | QColor titleColor( palette.button().color() ); |
1536 | QColor textColor( palette.buttonText().color() ); |
1537 | |
1538 | painter->setPen(titleColor); |
1539 | painter->setBrush(titleColor); |
1540 | painter->drawRect(option.rectF); |
1541 | |
1542 | QString value = calendar->weekDayName( daynum, KCalendarSystem::ShortDayName ); |
1543 | //kDebug(planDbg())<<daynum<<": "<<value; |
1544 | if ( model ) { |
1545 | QVariant v = model->weekDayData( daynum, Qt::DisplayRole ); |
1546 | if ( v.isValid() ) { |
1547 | value = v.toString(); |
1548 | } |
1549 | } |
1550 | painter->setPen( textColor ); |
1551 | painter->drawText(option.rectF, option.textAlignment, value, &rect); |
1552 | |
1553 | // painter->setPen( palette.color(QPalette::Text) ); |
1554 | // painter->drawLine(QPointF(0, option.rectF.height()), QPointF(option.rectF.width(), option.rectF.height())); |
1555 | |
1556 | painter->restore(); |
1557 | return rect; |
1558 | } |
1559 | |
1560 | //--------- |
1561 | KDateTableWeekNumberDelegate::KDateTableWeekNumberDelegate( QObject *parent ) |
1562 | : QObject( parent ) |
1563 | { |
1564 | } |
1565 | |
1566 | QVariant KDateTableWeekNumberDelegate::data( int week, int role, KDateTableDataModel *model ) |
1567 | { |
1568 | //kDebug(planDbg())<<week<<role<<model; |
1569 | if ( model == 0 ) { |
1570 | return QVariant(); |
1571 | } |
1572 | return model->weekNumberData( week, role ); |
1573 | } |
1574 | |
1575 | QRectF KDateTableWeekNumberDelegate::( QPainter *painter, const StyleOptionHeader &option, int week, KDateTableDataModel *model ) |
1576 | { |
1577 | //kDebug(planDbg()); |
1578 | painter->save(); |
1579 | QRectF result; |
1580 | QFont font = KGlobalSettings::generalFont(); |
1581 | painter->setFont(font); |
1582 | |
1583 | QColor titleColor( option.palette.button().color() ); |
1584 | QColor textColor( option.palette.buttonText().color() ); |
1585 | |
1586 | painter->setPen(titleColor); |
1587 | painter->setBrush(titleColor); |
1588 | painter->drawRect(option.rectF); |
1589 | painter->setPen(textColor); |
1590 | |
1591 | QString value = QString("%1" ).arg( week ); |
1592 | if ( model ) { |
1593 | QVariant v = model->weekNumberData( week, Qt::DisplayRole ); |
1594 | if ( v.isValid() ) { |
1595 | value = v.toString(); |
1596 | } |
1597 | } |
1598 | painter->drawText(option.rectF, option.textAlignment, value, &result); |
1599 | |
1600 | // painter->setPen(option.palette.color(QPalette::Text)); |
1601 | // painter->drawLine(QPointF(option.rectF.width(), 0), QPointF(option.rectF.width(), option.rectF.height())); |
1602 | |
1603 | painter->restore(); |
1604 | return result; |
1605 | } |
1606 | |
1607 | } //namespace KPlato |
1608 | |
1609 | #include "kdatetable.moc" |
1610 | #include "kdatetable_p.moc" |
1611 | |