kplato

kptdatetable.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
3 (C) 1998-2001 Mirko Boehm (mirko@kde.org)
4 (C) 2004-2006 Dag Andersen <danders@get2net.dk>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "kptdatetable.h"
23#include "kptmap.h"
24
25#include <tdeapplication.h>
26#include <knotifyclient.h>
27#include <kcalendarsystem.h>
28
29#include <tqdatetime.h>
30#include <tqstring.h>
31#include <tqpen.h>
32#include <tqpainter.h>
33#include <tqdialog.h>
34#include <assert.h>
35#include <tqlayout.h>
36#include <tqvaluelist.h>
37#include <tdeglobalsettings.h>
38
39#include <kdebug.h>
40
41namespace KPlato
42{
43
44DateValidator::DateValidator(TQWidget* parent, const char* name)
45 : TQValidator(parent, name)
46{
47}
48
49TQValidator::State
50DateValidator::validate(TQString& text, int&) const
51{
52 TQDate temp;
53 // ----- everything is tested in date():
54 return date(text, temp);
55}
56
57TQValidator::State
58DateValidator::date(const TQString& text, TQDate& d) const
59{
60 TQDate tmp = TDEGlobal::locale()->readDate(text);
61 if (!tmp.isNull())
62 {
63 d = tmp;
64 return Acceptable;
65 } else
66 return Valid;
67}
68
69void
70DateValidator::fixup( TQString& ) const
71{
72
73}
74
75
76DateTable::DateTable(TQWidget *parent, TQDate date_, const char* name, WFlags f)
77 : TQGridView(parent, name, f),
78 m_enabled(true)
79{
80 //kdDebug()<<k_funcinfo<<endl;
81 m_dateStartCol = 1;
82 m_selectedDates.clear();
83 m_selectedWeekdays.clear();
84
85 TQPair<int, int> p(0,0);
86 m_weeks.fill(p, 7);
87
88 setFontSize(10);
89 if(!date_.isValid()) {
90 kdError() <<k_funcinfo<<"Given date is invalid, using current date." << endl;
91 date_=TQDate::currentDate();
92 }
93 setFocusPolicy( TQWidget::StrongFocus );
94 setNumCols(7+m_dateStartCol); // 7 days a week + maybe 1 for weeknumbers
95 setNumRows(7); // 6 weeks max + headline
96
97 setHScrollBarMode(AlwaysOff);
98 setVScrollBarMode(AlwaysOff);
99 viewport()->setEraseColor(TDEGlobalSettings::baseColor());
100 setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
101
102 colorBackgroundHoliday = TQColor(0, 245, 255, TQColor::Hsv);
103 //colorBackgroundHoliday = colorBackgroundHoliday.light();
104 colorBackgroundWorkday = TQColor(208, 230, 240, TQColor::Hsv);;
105 //colorBackgroundWorkday = colorBackgroundWorkday.light();
106 colorTextHoliday = black;
107 colorTextWorkday = black;
108 colorLine = black;
109 backgroundSelectColor = TDEGlobalSettings::highlightColor();
110 penSelectColor=TDEGlobalSettings::baseColor();
111
112}
113
114void DateTable::paintWeekday(TQPainter *painter, int col) {
115 TQRect rect;
116 int w=cellWidth();
117 int h=cellHeight();
118
119 TQFont font = TDEGlobalSettings::generalFont();
120 font.setBold(true);
121 if (!m_enabled)
122 font.setItalic(true);
123 painter->setFont(font);
124
125 int day = weekday(col);
126
127 //kdDebug()<<k_funcinfo<<" col="<<col<<" day="<<day<<" name="<<daystr<<endl;
128
129 painter->setBrush(TDEGlobalSettings::baseColor());
130 painter->setPen(TDEGlobalSettings::baseColor());
131 painter->drawRect(0, 0, w, h);
132 painter->setPen(TDEGlobalSettings::textColor());
133
134 if (m_markedWeekdays.state(day) == Map::Working) {
135 painter->setPen(colorBackgroundWorkday);
136 painter->setBrush(colorBackgroundWorkday);
137 painter->drawRect(0, 0, w, h);
138 painter->setPen(colorTextWorkday);
139 } else if (m_markedWeekdays.state(day) == Map::NonWorking) {
140 painter->setPen(colorBackgroundHoliday);
141 painter->setBrush(colorBackgroundHoliday);
142 painter->drawRect(0, 0, w, h);
143 painter->setPen(colorTextHoliday);
144 }
145 if (m_selectedWeekdays.contains(day)) {
146 painter->setPen(backgroundSelectColor);
147 painter->setBrush(backgroundSelectColor);
148 painter->drawRect(2, 2, w-4, h-4);
149 painter->setPen(penSelectColor);
150 }
151 painter->drawText(0, 0, w, h-1, AlignCenter, TDEGlobal::locale()->calendar()->weekDayName(day, true), -1, &rect);
152 painter->setPen(colorLine);
153 painter->moveTo(0, h-1);
154 painter->lineTo(w-1, h-1);
155
156 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
157 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
158
159 //kdDebug()<<k_funcinfo<<"headline: row,col=("<<row<<","<<col<<")"<<" day="<<daystr<<endl;
160}
161
162void DateTable::paintWeekNumber(TQPainter *painter, int row) {
163 TQRect rect;
164 int w=cellWidth();
165 int h=cellHeight();
166
167 TQFont font=TDEGlobalSettings::generalFont();
168 font.setBold(true);
169 if (!m_enabled)
170 font.setItalic(true);
171 painter->setFont(font);
172
173 painter->setBrush(TDEGlobalSettings::baseColor());
174 painter->setPen(TDEGlobalSettings::baseColor());
175 painter->drawRect(0, 0, w, h);
176 painter->setPen(TDEGlobalSettings::textColor());
177
178 painter->drawText(0, 0, w, h-1, AlignCenter, TQString("%1").arg(m_weeks[row].first), -1, &rect);
179 painter->setPen(colorLine);
180 painter->moveTo(w-1, 0);
181 painter->lineTo(w-1, h-1);
182
183 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
184 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
185}
186
187void DateTable::paintDay(TQPainter *painter, int row, int col) {
188 //kdDebug()<<k_funcinfo<<"row,col=("<<row<<","<<col<<")"<<" num col="<<numCols()<<endl;
189 TQRect rect;
190 int w=cellWidth();
191 int h=cellHeight();
192
193 TQFont font=TDEGlobalSettings::generalFont();
194 font.setPointSize(fontsize);
195 if (!m_enabled)
196 font.setItalic(true);
197 painter->setFont(font);
198
199 TQDate d = getDate(position(row, col));
200
201 painter->setBrush(TDEGlobalSettings::baseColor());
202 painter->setPen(TDEGlobalSettings::baseColor());
203 painter->drawRect(0, 0, w, h);
204
205 // First paint the dates background
206 if (m_markedDates.state(d) == Map::NonWorking) {
207 //kdDebug()<<k_funcinfo<<"Marked date: "<<d<<" row,col=("<<row<<","<<col<<")=NonWorking"<<endl;
208 painter->setPen(colorBackgroundHoliday);
209 painter->setBrush(colorBackgroundHoliday);
210 painter->drawRect(0, 0, w, h);
211 } else if (m_markedDates.state(d) == Map::Working) {
212 //kdDebug()<<k_funcinfo<<"Marked date: "<<d<<" row,col=("<<row<<","<<col<<")=Working"<<endl;
213 painter->setPen(colorBackgroundWorkday);
214 painter->setBrush(colorBackgroundWorkday);
215 painter->drawRect(0, 0, w, h);
216 }
217 if(m_selectedDates.contains(d)) {
218 //kdDebug()<<k_funcinfo<<"Selected: "<<d<<" row,col=("<<row<<","<<col<<")"<<endl;
219 painter->setPen(backgroundSelectColor);
220 painter->setBrush(backgroundSelectColor);
221 painter->drawRect(2, 2, w-4, h-4);
222 }
223 // If weeks or weekdays are selected/marked we draw lines around the date
224 TQPen pen = painter->pen();
225 if (m_markedWeekdays.state(weekday(col)) == Map::Working) {
226 //kdDebug()<<k_funcinfo<<"Marked weekday: row,dayCol=("<<row<<","<<dayCol<<")=Working"<<endl;
227 pen.setColor(colorBackgroundWorkday);
228 painter->setPen(pen);
229 painter->moveTo(0, 0);
230 painter->lineTo(0, h-1);
231 painter->moveTo(w-1, 0);
232 painter->lineTo(w-1, h-1);
233 }
234 // then paint square if current date
235 if (d == TQDate::currentDate()) {
236 painter->setPen(colorLine);
237 painter->drawRect(1, 1, w-2, h-2);
238 }
239
240 // and now the day number
241 d.month() == date.month() ? painter->setPen(TDEGlobalSettings::textColor()) : painter->setPen(gray);
242 painter->drawText(0, 0, w, h, AlignCenter, TQString().setNum(d.day()), -1, &rect);
243
244 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
245 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
246}
247
248void DateTable::paintCell(TQPainter *painter, int row, int col) {
249 //kdDebug()<<k_funcinfo<<"row,col=("<<row<<","<<col<<")"<<"enabled="<<m_enabled<<endl;
250 if (row == 0 && col == 0) {
251 painter->save();
252 int w=cellWidth();
253 int h=cellHeight();
254 painter->setPen(colorLine);
255 painter->setBrush(TDEGlobalSettings::baseColor());
256 painter->moveTo(w-1, 0);
257 painter->lineTo(w-1, h-1);
258 painter->lineTo(0, h-1);
259 painter->restore();
260 return;
261 }
262 painter->save();
263 if(row==0) { // we are drawing the weekdays
264 paintWeekday(painter, col);
265 } else if (col == 0) { // draw week numbers
266 paintWeekNumber(painter, row);
267 } else { // draw the day
268 paintDay(painter, row, col);
269 }
270 painter->restore();
271}
272
273//FIXME
274void DateTable::keyPressEvent( TQKeyEvent *e ) {
275 if (!m_enabled)
276 return;
277 if ( e->key() == TQt::Key_Prior ) {
278 setDate(date.addMonths(-1));
279 return;
280 }
281 if ( e->key() == TQt::Key_Next ) {
282 setDate(date.addMonths(1));
283 return;
284 }
285
286 if ( e->key() == TQt::Key_Up ) {
287 if ( date.day() > 7 ) {
288 setDate(date.addDays(-7));
289 return;
290 }
291 }
292 if ( e->key() == TQt::Key_Down ) {
293 if ( date.day() <= date.daysInMonth()-7 ) {
294 setDate(date.addDays(7));
295 return;
296 }
297 }
298 if ( e->key() == TQt::Key_Left ) {
299 if ( date.day() > 1 ) {
300 setDate(date.addDays(-1));
301 return;
302 }
303 }
304 if ( e->key() == TQt::Key_Right ) {
305 if ( date.day() < date.daysInMonth() ) {
306 setDate(date.addDays(1));
307 return;
308 }
309 }
310
311 if ( e->key() == TQt::Key_Minus ) {
312 setDate(date.addDays(-1));
313 return;
314 }
315 if ( e->key() == TQt::Key_Plus ) {
316 setDate(date.addDays(1));
317 return;
318 }
319 if ( e->key() == TQt::Key_N ) {
320 setDate(TQDate::currentDate());
321 return;
322 }
323 if ( e->key() == TQt::Key_Control ) {
324 return;
325 }
326 if ( e->key() == TQt::Key_Shift ) {
327 return;
328 }
329
330 KNotifyClient::beep();
331}
332
333void DateTable::viewportResizeEvent(TQResizeEvent * e) {
334 TQGridView::viewportResizeEvent(e);
335
336 setCellWidth(viewport()->width()/numCols());
337 setCellHeight(viewport()->height()/numRows());
338}
339
340void DateTable::setFontSize(int size) {
341 int count;
342 TQFontMetrics metrics(fontMetrics());
343 TQRect rect;
344 // ----- store rectangles:
345 fontsize=size;
346 // ----- find largest day name:
347 maxCell.setWidth(0);
348 maxCell.setHeight(0);
349 for(count=0; count<7; ++count)
350 {
351 rect=metrics.boundingRect(TDEGlobal::locale()->calendar()->weekDayName(count+1, true));
352 maxCell.setWidth(TQMAX(maxCell.width(), rect.width()));
353 maxCell.setHeight(TQMAX(maxCell.height(), rect.height()));
354 }
355 // ----- compare with a real wide number and add some space:
356 rect=metrics.boundingRect(TQString::fromLatin1("88"));
357 maxCell.setWidth(TQMAX(maxCell.width()+2, rect.width()));
358 maxCell.setHeight(TQMAX(maxCell.height()+4, rect.height()));
359}
360
361//FIXME
362void DateTable::wheelEvent ( TQWheelEvent * e ) {
363 setDate(date.addMonths( -(int)(e->delta()/120)) );
364 e->accept();
365}
366
367
368void DateTable::contentsMousePressEvent(TQMouseEvent *e) {
369 if (!m_enabled)
370 return;
371 //kdDebug()<<k_funcinfo<<endl;
372 if(e->type()!=TQEvent::MouseButtonPress) {
373 return;
374 }
375 TQPoint mouseCoord = e->pos();
376 int row=rowAt(mouseCoord.y());
377 int col=columnAt(mouseCoord.x());
378 if (row == 0 && col == 0) { // user clicked on (unused) upper left square
379 updateSelectedCells();
380 m_selectedWeekdays.clear();
381 m_selectedDates.clear();
382 repaintContents(false);
383 emit selectionCleared();
384 return;
385 }
386 if (col == 0) { // user clicked on week numbers
387 updateSelectedCells();
388 m_selectedWeekdays.clear();
389 m_selectedDates.clear();
390 updateSelectedCells();
391 repaintContents(false);
392 return;
393 }
394 if (row==0 && col>0) { // the user clicked on weekdays
395 updateSelectedCells();
396 m_selectedDates.clear();
397 int day = weekday(col);
398 if (e->state() & ShiftButton) {
399 // select all days between this and the furthest away selected day,
400 // check first downside - then upside, clear all others
401 bool select = false;
402 for(int i=m_dateStartCol; i < col; ++i) {
403 //kdDebug()<<"Down["<<i<<"]: col="<<col<<" day="<<day<<" column(i)="<<column(i)<<endl;
404 if (m_selectedWeekdays.contains(weekday(i))) {
405 select = true; // we have hit a selected day; select the rest
406 } else if (select) {
407 m_selectedWeekdays.toggle(weekday(i)); // select
408 }
409 }
410 bool selected = select;
411 select = false;
412 for(int i=7; i > col; --i) {
413 //kdDebug()<<"Up["<<i<<"]: col="<<col<<" day="<<day<<" column(i)="<<column(i)<<endl;
414 if (m_selectedWeekdays.contains(weekday(i))) {
415 if (selected) m_selectedWeekdays.toggle(weekday(i)); // deselect
416 else select = true;
417 } else if (select) {
418 m_selectedWeekdays.toggle(weekday(i)); // select
419 }
420 }
421 if (!m_selectedWeekdays.contains(day)) {
422 m_selectedWeekdays.toggle(day); // always select
423 }
424 } else if (e->state() & ControlButton) {
425 // toggle select this date
426 m_selectedWeekdays.toggle(day);
427 } else {
428 // toggle select this, clear all others
429 m_selectedWeekdays.toggleClear(day);
430 }
431 updateSelectedCells();
432 repaintContents(false);
433 if (m_enabled) {
434 //kdDebug()<<k_funcinfo<<"emit weekdaySelected("<<day<<")"<<endl;
435 emit weekdaySelected(day); // day= 1..7
436 }
437 return;
438 }
439
440 if (contentsMousePressEvent_internal(e)) {
441 // Date hit,
442 m_selectedWeekdays.clear();
443 if (e->state() & ShiftButton) {
444 // find first&last date
445 TQDate first;
446 TQDate last;
447 DateMap::ConstIterator it;
448 for (it = m_selectedDates.constBegin(); it != m_selectedDates.constEnd(); ++it) {
449 //kdDebug()<<k_funcinfo<<it.key()<<endl;
450 TQDate d = TQDate::fromString(it.key(), TQt::ISODate);
451 if (!d.isValid())
452 continue;
453 if (!first.isValid() || first > d)
454 first = d;
455 if (!last.isValid() || last < d)
456 last = d;
457 }
458 // select between anchor and pressed date inclusive
459 m_selectedDates.clear();
460 if (first.isValid() && last.isValid()) {
461 TQDate anchor = first < date ? first : last;
462 int i = anchor > date ? -1 : 1;
463 while (anchor != date) {
464 //kdDebug()<<k_funcinfo<<anchor.toString(TQt::ISODate)<<endl;
465 m_selectedDates.toggle(anchor);
466 anchor = anchor.addDays(i);
467 }
468 }
469 m_selectedDates.toggle(date);
470 } else if (e->state() & ControlButton) {
471 // toggle select this date
472 m_selectedDates.toggle(date);
473 //kdDebug()<<k_funcinfo<<"toggle date: "<<date.toString()<<" state="<<m_selectedDates.state(date)<<endl;
474 } else {
475 // Select this, clear all others
476 m_selectedDates.clear();
477 m_selectedDates.toggleClear(date);
478 //kdDebug()<<k_funcinfo<<"toggleClear date: "<<date.toString()<<" state="<<m_selectedDates.state(date)<<endl;
479 }
480 }
481 repaintContents(false);
482}
483
484bool DateTable::contentsMousePressEvent_internal(TQMouseEvent *e) {
485 TQPoint mouseCoord = e->pos();
486 int row=rowAt(mouseCoord.y());
487 int col=columnAt(mouseCoord.x());
488 if(row<1 || col<0) { // the user clicked on the frame of the table
489 return false;
490 }
491 //kdDebug()<<k_funcinfo<<"pos["<<row<<","<<col<<"]="<<position(row,col)<<" firstday="<<firstday<<endl;
492 selectDate(getDate(position(row, col)));
493 return true;
494}
495
496bool DateTable::selectDate(const TQDate& date_) {
497 //kdDebug()<<k_funcinfo<<"date="<<date_.toString()<<endl;
498 bool changed=false;
499 TQDate temp;
500 // -----
501 if(!date_.isValid()) {
502 return false;
503 }
504 if(date!=date_) {
505 date=date_;
506 changed=true;
507 }
508
509 temp.setYMD(date.year(), date.month(), 1);
510 firstday=column(TDEGlobal::locale()->calendar()->dayOfWeek(temp));
511 if(firstday==1) firstday=8; // Reserve row 1 for previous month
512 numdays=date.daysInMonth();
513 if(date.month()==1) { // set to december of previous year
514 temp.setYMD(date.year()-1, 12, 1);
515 setWeekNumbers(TQDate(date.year()-1, 12, 31));
516 } else { // set to previous month
517 temp.setYMD(date.year(), date.month()-1, 1);
518 TQDate d(date.year(), date.month()-1,1);
519 setWeekNumbers(d.addDays(d.daysInMonth()-1));
520 }
521 numDaysPrevMonth=temp.daysInMonth();
522 if(changed) {
523 repaintContents(false);
524 }
525 if (m_enabled)
526 emit(dateChanged(date));
527 return true;
528}
529
530bool DateTable::setDate(const TQDate& date_, bool repaint) {
531 //kdDebug()<<k_funcinfo<<"date="<<date_.toString()<<endl;
532 bool changed=false;
533 TQDate temp;
534 // -----
535 if(!date_.isValid()) {
536 //kdDebug() << "DateTable::setDate: refusing to set invalid date." << endl;
537 return false;
538 }
539 if(date!=date_) {
540 date=date_;
541 changed=true;
542 }
543 //m_selectedDates.clear();
544
545 temp.setYMD(date.year(), date.month(), 1);
546 firstday=column(TDEGlobal::locale()->calendar()->dayOfWeek(temp));
547 if(firstday==1) firstday=8;
548 //kdDebug()<<k_funcinfo<<"date="<<temp<<"day="<<(TDEGlobal::locale()->calendar()->dayOfWeek(temp))<<" firstday="<<firstday<<endl;
549 numdays=date.daysInMonth();
550 if(date.month()==1) { // set to december of previous year
551 temp.setYMD(date.year()-1, 12, 1);
552 setWeekNumbers(TQDate(date.year()-1, 12, 31));
553 } else { // set to previous month
554 temp.setYMD(date.year(), date.month()-1, 1);
555 TQDate d(date.year(), date.month()-1,1);
556 setWeekNumbers(d.addDays(d.daysInMonth()-1));
557 }
558/* if (m_selectedWeekdays.isEmpty() &&
559 !m_selectedDates.isEmpty() && !m_selectedDates.contains(date))
560 {
561 //kdDebug()<<k_funcinfo<<"date inserted"<<endl;
562 m_selectedDates.insert(date);
563 }*/
564 numDaysPrevMonth=temp.daysInMonth();
565 if(changed && repaint) {
566 repaintContents(false);
567 }
568 if (m_enabled)
569 emit(dateChanged(date));
570 return true;
571}
572
573const TQDate& DateTable::getDate() const {
574 return date;
575}
576
577void DateTable::focusInEvent( TQFocusEvent *e ) {
578 TQGridView::focusInEvent( e );
579}
580
581void DateTable::focusOutEvent( TQFocusEvent *e ) {
582 TQGridView::focusOutEvent( e );
583}
584
585TQSize DateTable::sizeHint() const {
586 if(maxCell.height()>0 && maxCell.width()>0) {
587 return TQSize(maxCell.width()*numCols()+2*frameWidth(),
588 (maxCell.height()+2)*numRows()+2*frameWidth());
589 } else {
590 //kdDebug() << "DateTable::sizeHint: obscure failure - " << endl;
591 return TQSize(-1, -1);
592 }
593}
594
595void DateTable::setWeekNumbers(TQDate date) {
596 if (!date.isValid()) {
597 kdError()<<k_funcinfo<<"Invalid date"<<endl;
598 }
599 TQDate d(date);
600 for (int i = 1; i < 7; ++i) {
601 m_weeks[i].first = d.weekNumber(&(m_weeks[i].second));
602 //kdDebug()<<k_funcinfo<<"date="<<d.toString()<<" week=("<<m_weeks[i].first<<","<<m_weeks[i].second<<")"<<endl;
603 d = d.addDays(7);
604 }
605}
606
607void DateTable::updateCells() {
608 //kdDebug()<<k_funcinfo<<endl;
609 for (int row=0; row < numRows(); ++row) {
610 for (int col=0; col < numCols(); ++col) {
611 updateCell(row, col);
612 }
613 }
614}
615
616void DateTable::updateSelectedCells() {
617 //kdDebug()<<k_funcinfo<<endl;
618 TQDate dt(date.year(), date.month(), 1);
619 dt = dt.addDays(-firstday);
620 for (int pos=0; pos < 42; ++pos) {
621 if (m_selectedDates.contains(dt.addDays(pos)) ||
622 m_selectedWeekdays.contains(pos%7+1))
623 {
624 updateCell(pos/7+1, pos%7+1);
625 //kdDebug()<<k_funcinfo<<" update cell ("<<pos/7+1<<","<<pos%7+1<<") date="<<dt.addDays(pos).toString()<<endl;
626 }
627 }
628}
629
630void DateTable::updateMarkedCells() {
631 TQDate dt(date.year(), date.month(), 1);
632 dt = dt.addDays(-firstday);
633 for (int pos=0; pos < 42; ++pos) {
634 if (m_markedDates.contains(dt.addDays(pos)) ||
635 m_markedWeekdays.contains(pos%7+1))
636 {
637 updateCell(pos/7+1, pos%7+1);
638 //kdDebug()<<k_funcinfo<<" update cell ("<<pos/7+1<<","<<pos%7+1<<") date="<<dt.addDays(pos).toString()<<endl;
639 }
640 }
641}
642
643void DateTable::setMarkedWeekdays(const IntMap days) {
644 updateMarkedCells();
645 m_markedWeekdays.clear();
646 m_markedWeekdays = days;
647 updateMarkedCells();
648 repaintContents(false);
649}
650
651bool DateTable::weekdayMarked(int day) {
652 return m_markedWeekdays.contains(day);
653}
654
655bool DateTable::dateMarked(TQDate date) {
656 return m_markedDates[date.toString()];
657}
658
659TQDate DateTable::getDate(int pos) const {
660 return TQDate(date.year(), date.month(), 1).addDays(pos-firstday);
661}
662
663int DateTable::weekday(int col) const {
664 int day = col - m_dateStartCol + TDEGlobal::locale()->weekStartDay();
665 if (day > 7) day %= 7;
666 //kdDebug()<<k_funcinfo<<"col="<<col<<" day="<<day<<" StartCol="<<m_dateStartCol<<" weekStartDay="<<TDEGlobal::locale()->weekStartDay()<<endl;
667 return day;
668}
669
670int DateTable::column(int weekday) const {
671 int col = weekday - TDEGlobal::locale()->weekStartDay();
672 if (col < 0) col += 7;
673 //kdDebug()<<k_funcinfo<<"col="<<col<<" day="<<col<<" StartCol="<<m_dateStartCol<<" weekStartDay="<<TDEGlobal::locale()->weekStartDay()<<endl;
674 return col + m_dateStartCol;
675}
676
677void DateTable::clear() {
678 clearSelection();
679 m_markedDates.clear();
680 m_markedWeekdays.clear();
681 repaintContents(false);
682}
683
684void DateTable::clearSelection() {
685 m_selectedDates.clear();
686 m_selectedWeekdays.clear();
687 repaintContents(false);
688}
689
690 void DateTable::setEnabled(bool yes) {
691 if (m_enabled == yes)
692 return;
693 m_enabled=yes;
694 updateCells();
695}
696
697void DateTable::markSelected(int state) {
698 if (!m_selectedDates.isEmpty()) {
699 DateMap::iterator it;
700 for(it = m_selectedDates.begin(); it != m_selectedDates.end(); ++it) {
701 m_markedDates.insert(it.key(), state);
702 //kdDebug()<<k_funcinfo<<"marked date: "<<it.key()<<"="<<state<<endl;
703 }
704 } else if (!m_selectedWeekdays.isEmpty()) {
705 IntMap::iterator it;
706 for(it = m_selectedWeekdays.begin(); it != m_selectedWeekdays.end(); ++it) {
707 m_markedWeekdays.insert(it.key(), state);
708 //kdDebug()<<k_funcinfo<<"marked weekday: "<<it.key()<<"="<<state<<endl;
709 }
710 }
711 updateSelectedCells();
712 repaintContents(false);
713}
714
715DateInternalWeekSelector::DateInternalWeekSelector
716(int fontsize, TQWidget* parent, const char* name)
717 : TQLineEdit(parent, name),
718 val(new TQIntValidator(this)),
719 result(0)
720{
721 TQFont font;
722 // -----
723 font=TDEGlobalSettings::generalFont();
724 font.setPointSize(fontsize);
725 setFont(font);
726 setFrameStyle(TQFrame::NoFrame);
727 val->setRange(1, 53);
728 setValidator(val);
729 connect(this, TQ_SIGNAL(returnPressed()), TQ_SLOT(weekEnteredSlot()));
730}
731
732void
733DateInternalWeekSelector::weekEnteredSlot()
734{
735 bool ok;
736 int week;
737 // ----- check if this is a valid week:
738 week=text().toInt(&ok);
739 if(!ok)
740 {
741 KNotifyClient::beep();
742 return;
743 }
744 result=week;
745 emit(closeMe(1));
746}
747
748int
749DateInternalWeekSelector::getWeek() const
750{
751 return result;
752}
753
754void
755DateInternalWeekSelector::setWeek(int week)
756{
757 TQString temp;
758 // -----
759 temp.setNum(week);
760 setText(temp);
761}
762
763DateInternalMonthPicker::DateInternalMonthPicker
764(int fontsize, TQWidget* parent, const char* name)
765 : TQGridView(parent, name),
766 result(0) // invalid
767{
768 TQRect rect;
769 TQFont font;
770 // -----
771 activeCol = -1;
772 activeRow = -1;
773 font=TDEGlobalSettings::generalFont();
774 font.setPointSize(fontsize);
775 setFont(font);
776 setHScrollBarMode(AlwaysOff);
777 setVScrollBarMode(AlwaysOff);
778 setFrameStyle(TQFrame::NoFrame);
779 setNumRows(4);
780 setNumCols(3);
781 // enable to find drawing failures:
782 // setTableFlags(Tbl_clipCellPainting);
783 viewport()->setEraseColor(TDEGlobalSettings::baseColor()); // for consistency with the datepicker
784 // ----- find the preferred size
785 // (this is slow, possibly, but unfortunatly it is needed here):
786 TQFontMetrics metrics(font);
787 for(int i=1; i <= 12; ++i)
788 {
789 rect=metrics.boundingRect(TDEGlobal::locale()->calendar()->monthName(i, false));
790 if(max.width()<rect.width()) max.setWidth(rect.width());
791 if(max.height()<rect.height()) max.setHeight(rect.height());
792 }
793
794}
795
796TQSize
798{
799 return TQSize((max.width()+6)*numCols()+2*frameWidth(),
800 (max.height()+6)*numRows()+2*frameWidth());
801}
802
803int
805{
806 return result;
807}
808
809void
811{
812 p->setPen(TDEGlobalSettings::textColor());
813}
814
815void
817{
818 setCellWidth(width()/3);
819 setCellHeight(height()/4);
820}
821
822void
823DateInternalMonthPicker::paintCell(TQPainter* painter, int row, int col)
824{
825 int index;
826 TQString text;
827 // ----- find the number of the cell:
828 index=3*row+col+1;
829 text=TDEGlobal::locale()->calendar()->monthName(index, false);
830 painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
831 if ( activeCol == col && activeRow == row )
832 painter->drawRect( 0, 0, cellWidth(), cellHeight() );
833}
834
835void
837{
838 if(!isEnabled() || e->button() != TQt::LeftButton)
839 {
840 KNotifyClient::beep();
841 return;
842 }
843 // -----
844 int row, col;
845 TQPoint mouseCoord;
846 // -----
847 mouseCoord = e->pos();
848 row=rowAt(mouseCoord.y());
849 col=columnAt(mouseCoord.x());
850
851 if(row<0 || col<0)
852 { // the user clicked on the frame of the table
853 activeCol = -1;
854 activeRow = -1;
855 } else {
856 activeCol = col;
857 activeRow = row;
858 updateCell( row, col /*, false */ );
859 }
860}
861
862void
863DateInternalMonthPicker::contentsMouseMoveEvent(TQMouseEvent *e)
864{
865 if (e->state() & TQt::LeftButton)
866 {
867 int row, col;
868 TQPoint mouseCoord;
869 // -----
870 mouseCoord = e->pos();
871 row=rowAt(mouseCoord.y());
872 col=columnAt(mouseCoord.x());
873 int tmpRow = -1, tmpCol = -1;
874 if(row<0 || col<0)
875 { // the user clicked on the frame of the table
876 if ( activeCol > -1 )
877 {
878 tmpRow = activeRow;
879 tmpCol = activeCol;
880 }
881 activeCol = -1;
882 activeRow = -1;
883 } else {
884 bool differentCell = (activeRow != row || activeCol != col);
885 if ( activeCol > -1 && differentCell)
886 {
887 tmpRow = activeRow;
888 tmpCol = activeCol;
889 }
890 if ( differentCell)
891 {
892 activeRow = row;
893 activeCol = col;
894 updateCell( row, col /*, false */ ); // mark the new active cell
895 }
896 }
897 if ( tmpRow > -1 ) // repaint the former active cell
898 updateCell( tmpRow, tmpCol /*, true */ );
899 }
900}
901
902void
904{
905 if(!isEnabled())
906 {
907 return;
908 }
909 // -----
910 int row, col, pos;
911 TQPoint mouseCoord;
912 // -----
913 mouseCoord = e->pos();
914 row=rowAt(mouseCoord.y());
915 col=columnAt(mouseCoord.x());
916 if(row<0 || col<0)
917 { // the user clicked on the frame of the table
918 emit(closeMe(0));
919 }
920 pos=3*row+col+1;
921 result=pos;
922 emit(closeMe(1));
923}
924
925
926
927DateInternalYearSelector::DateInternalYearSelector
928(int fontsize, TQWidget* parent, const char* name)
929 : TQLineEdit(parent, name),
930 val(new TQIntValidator(this)),
931 result(0)
932{
933 TQFont font;
934 // -----
935 font=TDEGlobalSettings::generalFont();
936 font.setPointSize(fontsize);
937 setFont(font);
938 setFrameStyle(TQFrame::NoFrame);
939 // we have to respect the limits of TQDate here, I fear:
940 val->setRange(0, 8000);
941 setValidator(val);
942 connect(this, TQ_SIGNAL(returnPressed()), TQ_SLOT(yearEnteredSlot()));
943}
944
945void
946DateInternalYearSelector::yearEnteredSlot()
947{
948 bool ok;
949 int year;
950 TQDate date;
951 // ----- check if this is a valid year:
952 year=text().toInt(&ok);
953 if(!ok)
954 {
955 KNotifyClient::beep();
956 return;
957 }
958 date.setYMD(year, 1, 1);
959 if(!date.isValid())
960 {
961 KNotifyClient::beep();
962 return;
963 }
964 result=year;
965 emit(closeMe(1));
966}
967
968int
969DateInternalYearSelector::getYear() const
970{
971 return result;
972}
973
974void
975DateInternalYearSelector::setYear(int year)
976{
977 TQString temp;
978 // -----
979 temp.setNum(year);
980 setText(temp);
981}
982
983PopupFrame::PopupFrame(TQWidget* parent, const char* name)
984 : TQFrame(parent, name, WType_Popup),
985 result(0), // rejected
986 main(0)
987{
988 setFrameStyle(TQFrame::Box|TQFrame::Raised);
989 setMidLineWidth(2);
990}
991
992void
994{
995 if(e->key()==Key_Escape)
996 {
997 result=0; // rejected
998 tqApp->exit_loop();
999 }
1000}
1001
1002void
1004{
1005 result=r;
1006 tqApp->exit_loop();
1007}
1008
1009void
1011{
1012 main=m;
1013 if(main!=0)
1014 {
1015 resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
1016 }
1017}
1018
1019void
1021{
1022 if(main!=0)
1023 {
1024 main->setGeometry(frameWidth(), frameWidth(),
1025 width()-2*frameWidth(), height()-2*frameWidth());
1026 }
1027}
1028
1029void
1030PopupFrame::popup(const TQPoint &pos)
1031{
1032 // Make sure the whole popup is visible.
1033 TQRect d = TQApplication::desktop()->screenGeometry(TQApplication::desktop()->screenNumber(pos));
1034 int x = pos.x();
1035 int y = pos.y();
1036 int w = width();
1037 int h = height();
1038 if (x+w > d.x()+d.width())
1039 x = d.width() - w;
1040 if (y+h > d.y()+d.height())
1041 y = d.height() - h;
1042 if (x < d.x())
1043 x = 0;
1044 if (y < d.y())
1045 y = 0;
1046
1047 // Pop the thingy up.
1048 move(x, y);
1049 show();
1050}
1051
1052int
1054{
1055 popup(pos);
1056 repaint();
1057 tqApp->enter_loop();
1058 hide();
1059 return result;
1060}
1061
1062int
1063PopupFrame::exec(int x, int y)
1064{
1065 return exec(TQPoint(x, y));
1066}
1067
1068void PopupFrame::virtual_hook( int, void* )
1069{ /*BASE::virtual_hook( id, data );*/ }
1070
1071void DateTable::virtual_hook( int, void* )
1072{ /*BASE::virtual_hook( id, data );*/ }
1073
1074} //KPlato namespace
1075
1076#include "kptdatetable.moc"
TQSize sizeHint() const
The size hint.
virtual void contentsMouseReleaseEvent(TQMouseEvent *e)
Emit monthSelected(int) when a cell has been released.
void closeMe(int)
This is send from the mouse click event handler.
int result
Store the month that has been clicked [1..12].
TQRect max
Contains the largest rectangle needed by the month names.
int getResult() const
Return the result.
virtual void contentsMousePressEvent(TQMouseEvent *e)
Catch mouse click and move events to paint a rectangle around the item.
virtual void viewportResizeEvent(TQResizeEvent *)
The resize event.
void setupPainter(TQPainter *p)
Set up the painter.
virtual void paintCell(TQPainter *painter, int row, int col)
Paint a cell.
short int activeCol
the cell under mouse cursor when LBM is pressed
TQWidget * main
The only subwidget that uses the whole dialog window.
void close(int r)
Close the popup window.
int result
The result.
int exec(TQPoint p)
Execute the popup window.
void setMainWidget(TQWidget *m)
Set the main widget.
void popup(const TQPoint &pos)
Open the popup window at position pos.
virtual void resizeEvent(TQResizeEvent *)
The resize event.
PopupFrame(TQWidget *parent=0, const char *name=0)
The contructor.
virtual void keyPressEvent(TQKeyEvent *e)
Catch key press events.