summaryrefslogtreecommitdiffabout
path: root/microkde/kdatetbl.cpp
Unidiff
Diffstat (limited to 'microkde/kdatetbl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kdatetbl.cpp735
1 files changed, 735 insertions, 0 deletions
diff --git a/microkde/kdatetbl.cpp b/microkde/kdatetbl.cpp
new file mode 100644
index 0000000..0a2d1f5
--- a/dev/null
+++ b/microkde/kdatetbl.cpp
@@ -0,0 +1,735 @@
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, 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 calender 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 <kglobal.h>
36#include <kglobalsettings.h>
37#include <kapplication.h>
38#include <klocale.h>
39#include <kdebug.h>
40#include <knotifyclient.h>
41#include "kdatetbl.h"
42#include <qdatetime.h>
43#include <qstring.h>
44#include <qpen.h>
45#include <qpainter.h>
46#include <qdialog.h>
47#include <assert.h>
48#include <qapplication.h>
49
50KDateValidator::KDateValidator(QWidget* parent, const char* name)
51 : QValidator(parent, name)
52{
53}
54
55QValidator::State
56KDateValidator::validate(QString& text, int&) const
57{
58 QDate temp;
59 // ----- everything is tested in date():
60 return date(text, temp);
61}
62
63QValidator::State
64KDateValidator::date(const QString& text, QDate& d) const
65{
66 QDate tmp = KGlobal::locale()->readDate(text);
67 if (!tmp.isNull())
68 {
69 d = tmp;
70 return Acceptable;
71 } else
72 return Valid;
73}
74
75void
76KDateValidator::fixup( QString& ) const
77{
78
79}
80
81KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f)
82 : QGridView(parent, name, f)
83{
84 setFontSize(10);
85 if(!date_.isValid())
86 {
87 date_=QDate::currentDate();
88 }
89 setFocusPolicy( QWidget::StrongFocus );
90 setNumRows(7); // 6 weeks max + headline
91 setNumCols(7); // 7 days a week
92 setHScrollBarMode(AlwaysOff);
93 setVScrollBarMode(AlwaysOff);
94 viewport()->setBackgroundColor(QColor(220,245,255));
95#if 0
96 viewport()->setEraseColor(lightGray);
97#endif
98 setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
99}
100
101void
102KDateTable::paintCell(QPainter *painter, int row, int col)
103{
104 QRect rect;
105 QString text;
106 QPen pen;
107 int w=cellWidth();
108 int h=cellHeight();
109 int pos;
110 QBrush brushBlue(blue);
111 QBrush brushLightblue(QColor(220,245,255));
112 QFont font=KGlobalSettings::generalFont();
113 // -----
114 font.setPointSize(fontsize);
115 if(row==0)
116 { // we are drawing the headline
117 font.setBold(true);
118 painter->setFont(font);
119 bool normalday = true;
120 QString daystr;
121 if (KGlobal::locale()->weekStartsMonday())
122 {
123 daystr = KGlobal::locale()->weekDayName(col+1, true);
124 if (col == 5 || col == 6)
125 normalday = false;
126 } else {
127 daystr = KGlobal::locale()->weekDayName(col==0? 7 : col, true);
128 if (col == 0 || col == 6)
129 normalday = false;
130 }
131 if (!normalday)
132 {
133 painter->setPen(QColor(220,245,255));
134 painter->setBrush(brushLightblue);
135 painter->drawRect(0, 0, w, h);
136 painter->setPen(blue);
137 } else {
138 painter->setPen(blue);
139 painter->setBrush(brushBlue);
140 painter->drawRect(0, 0, w, h);
141 painter->setPen(white);
142 }
143 painter->drawText(0, 0, w, h-1, AlignCenter,
144 daystr, -1, &rect);
145 painter->setPen(black);
146 painter->moveTo(0, h-1);
147 painter->lineTo(w-1, h-1);
148 // ----- draw the weekday:
149 } else {
150 painter->setFont(font);
151 pos=7*(row-1)+col;
152 if (KGlobal::locale()->weekStartsMonday())
153 pos++;
154 if(pos<firstday || (firstday+numdays<=pos))
155 { // we are either
156 // ° painting a day of the previous month or
157 // ° painting a day of the following month
158 if(pos<firstday)
159 { // previous month
160 text.setNum(numDaysPrevMonth+pos-firstday+1);
161 } else { // following month
162 text.setNum(pos-firstday-numdays+1);
163 }
164 painter->setPen(gray);
165 } else { // paint a day of the current month
166 text.setNum(pos-firstday+1);
167 painter->setPen(black);
168 }
169
170 pen=painter->pen();
171 if(firstday+date.day()-1==pos)
172 {
173 if(hasFocus())
174 { // draw the currently selected date
175 painter->setPen(red);
176 painter->setBrush(darkRed);
177 pen=white;
178 } else {
179 painter->setPen(darkGray);
180 painter->setBrush(darkGray);
181 pen=white;
182 }
183 } else {
184 painter->setBrush(QColor(220,245,255));
185 painter->setPen(QColor(220,245,255));
186 }
187 painter->drawRect(0, 0, w, h);
188 painter->setPen(pen);
189 painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect);
190 }
191 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
192 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
193}
194
195void
196KDateTable::keyPressEvent( QKeyEvent *e )
197{
198 /*
199 // not working properly
200 if ( e->key() == Qt::Key_Prior ) {
201 if ( date.month() == 1 ) {
202 KNotifyClient::beep();
203 return;
204 }
205 int day = date.day();
206 if ( day > 27 )
207 while ( !QDate::isValid( date.year(), date.month()-1, day ) )
208 day--;
209 setDate(QDate(date.year(), date.month()-1, day));
210 return;
211 }
212 if ( e->key() == Qt::Key_Next ) {
213 if ( date.month() == 12 ) {
214 KNotifyClient::beep();
215 return;
216 }
217 int day = date.day();
218 if ( day > 27 )
219 while ( !QDate::isValid( date.year(), date.month()+1, day ) )
220 day--;
221 setDate(QDate(date.year(), date.month()+1, day));
222 return;
223 }
224 */
225 int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0;
226
227 int temp=firstday+date.day()-dayoff;
228 int pos = temp;
229 bool irgnore = true;
230 if ( e->state() != Qt::ControlButton ) {
231 if ( e->key() == Qt::Key_Up ) {
232 pos -= 7;
233 irgnore = false;
234 }
235 if ( e->key() == Qt::Key_Down ) {
236 pos += 7;
237 irgnore = false;
238 }
239 if ( e->key() == Qt::Key_Left ) {
240 pos--;
241 irgnore = false;
242 }
243 if ( e->key() == Qt::Key_Right ) {
244 pos++;
245 irgnore = false;
246 }
247 }
248 if ( irgnore )
249 e->ignore();
250
251 if(pos+dayoff<=firstday)
252 { // this day is in the previous month
253 KNotifyClient::beep();
254 return;
255 }
256 if(firstday+numdays<pos+dayoff)
257 { // this date is in the next month
258 KNotifyClient::beep(i18n( "Month not long enough" ));
259 return;
260 }
261
262 if ( pos == temp )
263 return;
264
265 setDate(QDate(date.year(), date.month(), pos-firstday+dayoff));
266 updateCell(temp/7+1, temp%7); // Update the previously selected cell
267 updateCell(pos/7+1, pos%7); // Update the selected cell
268 assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid());
269
270
271}
272
273void
274KDateTable::viewportResizeEvent(QResizeEvent * e)
275{
276 QGridView::viewportResizeEvent(e);
277
278 setCellWidth(viewport()->width()/7);
279 setCellHeight(viewport()->height()/7);
280}
281
282void
283KDateTable::setFontSize(int size)
284{
285 int count;
286 QRect rect;
287 // ----- store rectangles:
288 fontsize=size;
289 QFont font = KGlobalSettings::generalFont();
290 font.setPointSize(fontsize);
291 font.setBold( true );
292 QFontMetrics metrics(font);
293
294 // ----- find largest day name:
295 maxCell.setWidth(0);
296 maxCell.setHeight(0);
297 for(count=0; count<7; ++count)
298 {
299 rect=metrics.boundingRect(KGlobal::locale()->weekDayName(count+1, true));
300 maxCell.setWidth(QMAX(maxCell.width(), rect.width()));
301 maxCell.setHeight(QMAX(maxCell.height(), rect.height()));
302 }
303 // ----- compare with a real wide number and add some space:
304 rect=metrics.boundingRect(QString::fromLatin1("88"));
305 maxCell.setWidth(QMAX(maxCell.width()+2, rect.width()));
306 maxCell.setHeight(QMAX(maxCell.height()+4, rect.height()));
307 if ( maxCell.width() * 1000 / maxCell.height() > 1900 )
308 maxCell.setHeight(maxCell.width() * 1000 / 1900 );
309}
310
311void
312KDateTable::contentsMousePressEvent(QMouseEvent *e)
313{
314 if(e->type()!=QEvent::MouseButtonPress)
315 { // the KDatePicker only reacts on mouse press events:
316 return;
317 }
318 if(!isEnabled())
319 {
320 KNotifyClient::beep();
321 return;
322 }
323
324 int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0;
325 // -----
326 int row, col, pos, temp;
327 QPoint mouseCoord;
328 // -----
329 mouseCoord = e->pos();
330 row=rowAt(mouseCoord.y());
331 col=columnAt(mouseCoord.x());
332 if(row<0 || col<0)
333 { // the user clicked on the frame of the table
334 return;
335 }
336 pos=7*(row-1)+col+1;
337 if(pos+dayoff<=firstday)
338 { // this day is in the previous month
339 KNotifyClient::beep();
340 return;
341 }
342 if(firstday+numdays<pos+dayoff)
343 { // this date is in the next month
344 KNotifyClient::beep();
345 return;
346 }
347 temp=firstday+date.day()-dayoff-1;
348 setDate(QDate(date.year(), date.month(), pos-firstday+dayoff));
349 updateCell(temp/7+1, temp%7); // Update the previously selected cell
350 updateCell(row, col); // Update the selected cell
351 // assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid());
352 emit(tableClicked());
353}
354
355bool
356KDateTable::setDate(const QDate& date_)
357{
358 bool changed=false;
359 QDate temp;
360 // -----
361 if(!date_.isValid())
362 {
363 kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl;
364 return false;
365 }
366 if(date!=date_)
367 {
368 date=date_;
369 changed=true;
370 }
371 temp.setYMD(date.year(), date.month(), 1);
372 firstday=temp.dayOfWeek();
373 if(firstday==1) firstday=8;
374 numdays=date.daysInMonth();
375 if(date.month()==1)
376 { // set to december of previous year
377 temp.setYMD(date.year()-1, 12, 1);
378 } else { // set to previous month
379 temp.setYMD(date.year(), date.month()-1, 1);
380 }
381 numDaysPrevMonth=temp.daysInMonth();
382 if(changed)
383 {
384 repaintContents(false);
385 }
386 emit(dateChanged(date));
387 return true;
388}
389
390const QDate&
391KDateTable::getDate() const
392{
393 return date;
394}
395
396void KDateTable::focusInEvent( QFocusEvent *e )
397{
398 repaintContents(false);
399 QGridView::focusInEvent( e );
400}
401
402void KDateTable::focusOutEvent( QFocusEvent *e )
403{
404 repaintContents(false);
405 QGridView::focusOutEvent( e );
406}
407
408QSize
409KDateTable::sizeHint() const
410{
411 if(maxCell.height()>0 && maxCell.width()>0)
412 {
413 return QSize((maxCell.width()+2)*numCols()+2*frameWidth(),
414 (maxCell.height()+4)*numRows()+2*frameWidth());
415 } else {
416 return QSize(-1, -1);
417 }
418}
419
420KDateInternalMonthPicker::KDateInternalMonthPicker
421(int fontsize, QWidget* parent, const char* name)
422 : QGridView(parent, name),
423 result(0) // invalid
424{
425 QRect rect;
426 QFont font;
427 // -----
428 activeCol = -1;
429 activeRow = -1;
430 font=KGlobalSettings::generalFont();
431 font.setPointSize(fontsize);
432 setFont(font);
433 setHScrollBarMode(AlwaysOff);
434 setVScrollBarMode(AlwaysOff);
435 setFrameStyle(QFrame::NoFrame);
436 setNumRows(4);
437 setNumCols(3);
438 // enable to find drawing failures:
439 // setTableFlags(Tbl_clipCellPainting);
440#if 0
441 viewport()->setEraseColor(lightGray); // for consistency with the datepicker
442#endif
443 // ----- find the preferred size
444 // (this is slow, possibly, but unfortunatly it is needed here):
445 QFontMetrics metrics(font);
446 for(int i=1; i <= 12; ++i)
447 {
448 rect=metrics.boundingRect(KGlobal::locale()->monthName(i, false));
449 if(max.width()<rect.width()) max.setWidth(rect.width());
450 if(max.height()<rect.height()) max.setHeight(rect.height());
451 }
452
453}
454
455QSize
456KDateInternalMonthPicker::sizeHint() const
457{
458 return QSize((max.width()+6)*numCols()+2*frameWidth(),
459 (max.height()+6)*numRows()+2*frameWidth());
460}
461
462int
463KDateInternalMonthPicker::getResult() const
464{
465 return result;
466}
467
468void
469KDateInternalMonthPicker::setupPainter(QPainter *p)
470{
471 p->setPen(black);
472}
473
474void
475KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*)
476{
477 setCellWidth(width()/3);
478 setCellHeight(height()/4);
479}
480
481void
482KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col)
483{
484 int index;
485 QString text;
486 // ----- find the number of the cell:
487 index=3*row+col+1;
488 text=KGlobal::locale()->monthName(index, false);
489 painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
490 if ( activeCol == col && activeRow == row )
491 painter->drawRect( 0, 0, cellWidth(), cellHeight() );
492}
493
494void
495KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e)
496{
497 if(!isEnabled() || e->button() != LeftButton)
498 {
499 KNotifyClient::beep();
500 return;
501 }
502 // -----
503 int row, col;
504 QPoint mouseCoord;
505 // -----
506 mouseCoord = e->pos();
507 row=rowAt(mouseCoord.y());
508 col=columnAt(mouseCoord.x());
509
510 if(row<0 || col<0)
511 { // the user clicked on the frame of the table
512 activeCol = -1;
513 activeRow = -1;
514 } else {
515 activeCol = col;
516 activeRow = row;
517 updateCell( row, col /*, false */ );
518 }
519}
520
521void
522KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e)
523{
524 if (e->state() & LeftButton)
525 {
526 int row, col;
527 QPoint mouseCoord;
528 // -----
529 mouseCoord = e->pos();
530 row=rowAt(mouseCoord.y());
531 col=columnAt(mouseCoord.x());
532 int tmpRow = -1, tmpCol = -1;
533 if(row<0 || col<0)
534 { // the user clicked on the frame of the table
535 if ( activeCol > -1 )
536 {
537 tmpRow = activeRow;
538 tmpCol = activeCol;
539 }
540 activeCol = -1;
541 activeRow = -1;
542 } else {
543 bool differentCell = (activeRow != row || activeCol != col);
544 if ( activeCol > -1 && differentCell)
545 {
546 tmpRow = activeRow;
547 tmpCol = activeCol;
548 }
549 if ( differentCell)
550 {
551 activeRow = row;
552 activeCol = col;
553 updateCell( row, col /*, false */ ); // mark the new active cell
554 }
555 }
556 if ( tmpRow > -1 ) // repaint the former active cell
557 updateCell( tmpRow, tmpCol /*, true */ );
558 }
559}
560
561void
562KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e)
563{
564 if(!isEnabled())
565 {
566 return;
567 }
568 // -----
569 int row, col, pos;
570 QPoint mouseCoord;
571 // -----
572 mouseCoord = e->pos();
573 row=rowAt(mouseCoord.y());
574 col=columnAt(mouseCoord.x());
575 if(row<0 || col<0)
576 { // the user clicked on the frame of the table
577 emit(closeMe(0));
578 }
579 pos=3*row+col+1;
580 result=pos;
581 emit(closeMe(1));
582}
583
584
585
586KDateInternalYearSelector::KDateInternalYearSelector
587(int fontsize, QWidget* parent, const char* name)
588 : QLineEdit(parent, name),
589 val(new QIntValidator(this)),
590 result(0)
591{
592 QFont font;
593 // -----
594 font=KGlobalSettings::generalFont();
595 font.setPointSize(fontsize);
596 setFont(font);
597#if 0
598 setFrameStyle(QFrame::NoFrame);
599#endif
600 // we have to respect the limits of QDate here, I fear:
601 val->setRange(0, 8000);
602 setValidator(val);
603 connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot()));
604}
605
606void
607KDateInternalYearSelector::yearEnteredSlot()
608{
609 bool ok;
610 int year;
611 QDate date;
612 // ----- check if this is a valid year:
613 year=text().toInt(&ok);
614 if(!ok)
615 {
616 KNotifyClient::beep();
617 return;
618 }
619 date.setYMD(year, 1, 1);
620 if(!date.isValid())
621 {
622 KNotifyClient::beep();
623 return;
624 }
625 result=year;
626 emit(closeMe(1));
627}
628
629int
630KDateInternalYearSelector::getYear()
631{
632 return result;
633}
634
635void
636KDateInternalYearSelector::setYear(int year)
637{
638 QString temp;
639 // -----
640 temp.setNum(year);
641 setText(temp);
642}
643
644KPopupFrame::KPopupFrame(QWidget* parent, const char* name)
645 : QFrame(parent, name, WType_Popup),
646 result(0), // rejected
647 main(0)
648{
649 setFrameStyle(QFrame::Box|QFrame::Raised);
650 setMidLineWidth(2);
651}
652
653void
654KPopupFrame::keyPressEvent(QKeyEvent* e)
655{
656 if(e->key()==Key_Escape)
657 {
658 result=0; // rejected
659 qApp->exit_loop();
660 }
661}
662
663void
664KPopupFrame::close(int r)
665{
666 result=r;
667 qApp->exit_loop();
668}
669
670void
671KPopupFrame::setMainWidget(QWidget* m)
672{
673 main=m;
674 if(main!=0)
675 {
676 resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
677 }
678}
679
680void
681KPopupFrame::resizeEvent(QResizeEvent*)
682{
683 if(main!=0)
684 {
685 main->setGeometry(frameWidth(), frameWidth(),
686 width()-2*frameWidth(), height()-2*frameWidth());
687 }
688}
689
690void
691KPopupFrame::popup(const QPoint &pos)
692{
693 // Make sure the whole popup is visible.
694 QRect d = QApplication::desktop()->frameGeometry();
695 int x = pos.x();
696 int y = pos.y();
697 int w = width();
698 int h = height();
699 if (x+w > d.x()+d.width())
700 x = d.width() - w;
701 if (y+h > d.y()+d.height())
702 y = d.height() - h;
703 if (x < d.x())
704 x = 0;
705 if (y < d.y())
706 y = 0;
707
708 // Pop the thingy up.
709 move(x, y);
710 show();
711}
712
713int
714KPopupFrame::exec(QPoint pos)
715{
716 popup(pos);
717 repaint();
718 qApp->enter_loop();
719 hide();
720 return result;
721}
722
723int
724KPopupFrame::exec(int x, int y)
725{
726 return exec(QPoint(x, y));
727}
728
729void KPopupFrame::virtual_hook( int, void* )
730{ /*BASE::virtual_hook( id, data );*/ }
731
732void KDateTable::virtual_hook( int, void* )
733{ /*BASE::virtual_hook( id, data );*/ }
734
735//#include "kdatetbl.moc"