Diffstat (limited to 'core/pim/datebook/datebookday.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/pim/datebook/datebookday.cpp | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/core/pim/datebook/datebookday.cpp b/core/pim/datebook/datebookday.cpp new file mode 100644 index 0000000..d5daab2 --- a/dev/null +++ b/core/pim/datebook/datebookday.cpp | |||
@@ -0,0 +1,553 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include "datebookday.h" | ||
22 | #include "datebookdayheaderimpl.h" | ||
23 | |||
24 | #include <qpe/datebookdb.h> | ||
25 | #include <qpe/resource.h> | ||
26 | #include <qpe/event.h> | ||
27 | #include <qpe/qpeapplication.h> | ||
28 | #include <qpe/timestring.h> | ||
29 | #include <qpe/qpedebug.h> | ||
30 | |||
31 | #include <qheader.h> | ||
32 | #include <qdatetime.h> | ||
33 | #include <qpainter.h> | ||
34 | #include <qsimplerichtext.h> | ||
35 | #include <qpopupmenu.h> | ||
36 | #include <qtextcodec.h> | ||
37 | #include <qpalette.h> | ||
38 | |||
39 | DateBookDayView::DateBookDayView( bool whichClock, QWidget *parent, | ||
40 | const char *name ) | ||
41 | : QTable( 24, 1, parent, name ), | ||
42 | ampm( whichClock ) | ||
43 | { | ||
44 | enableClipper(TRUE); | ||
45 | setTopMargin( 0 ); | ||
46 | horizontalHeader()->hide(); | ||
47 | setLeftMargin(38); | ||
48 | setColumnStretchable( 0, TRUE ); | ||
49 | setHScrollBarMode( QScrollView::AlwaysOff ); | ||
50 | verticalHeader()->setPalette(white); | ||
51 | verticalHeader()->setResizeEnabled(FALSE); | ||
52 | setSelectionMode( Single ); | ||
53 | |||
54 | // get rid of being able to edit things... | ||
55 | QTableItem *tmp; | ||
56 | int row; | ||
57 | for ( row = 0; row < numRows(); row++ ) { | ||
58 | tmp = new QTableItem( this, QTableItem::Never, QString::null); | ||
59 | setItem( row, 0, tmp ); | ||
60 | } | ||
61 | initHeader(); | ||
62 | QObject::connect( qApp, SIGNAL(clockChanged(bool)), | ||
63 | this, SLOT(slotChangeClock(bool)) ); | ||
64 | } | ||
65 | |||
66 | void DateBookDayView::initHeader() | ||
67 | { | ||
68 | QString strTmp; | ||
69 | for ( int i = 0; i < 24; ++i ) { | ||
70 | if ( ampm ) { | ||
71 | if ( i == 0 ) | ||
72 | strTmp = QString::number(12) + ":00"; | ||
73 | else if ( i == 12 ) | ||
74 | strTmp = QString::number(12) + tr(":00p"); | ||
75 | else if ( i > 12 ) | ||
76 | strTmp = QString::number( i - 12 ) + tr(":00p"); | ||
77 | else | ||
78 | strTmp = QString::number(i) + ":00"; | ||
79 | } else { | ||
80 | if ( i < 10 ) | ||
81 | strTmp = "0" + QString::number(i) + ":00"; | ||
82 | else | ||
83 | strTmp = QString::number(i) + ":00"; | ||
84 | } | ||
85 | strTmp = strTmp.rightJustify( 6, ' ' ); | ||
86 | verticalHeader()->setLabel( i, strTmp ); | ||
87 | setRowStretchable( i, FALSE ); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | void DateBookDayView::slotChangeClock( bool newClock ) | ||
92 | { | ||
93 | ampm = newClock; | ||
94 | initHeader(); | ||
95 | } | ||
96 | |||
97 | bool DateBookDayView::whichClock() const | ||
98 | { | ||
99 | return ampm; | ||
100 | } | ||
101 | |||
102 | void DateBookDayView::moveUp() | ||
103 | { | ||
104 | scrollBy(0, -20); | ||
105 | } | ||
106 | |||
107 | void DateBookDayView::moveDown() | ||
108 | { | ||
109 | scrollBy(0, 20); | ||
110 | } | ||
111 | |||
112 | void DateBookDayView::paintCell( QPainter *p, int, int, const QRect &cr, bool ) | ||
113 | { | ||
114 | int w = cr.width(); | ||
115 | int h = cr.height(); | ||
116 | p->fillRect( 0, 0, w, h, colorGroup().brush( QColorGroup::Base ) ); | ||
117 | if ( showGrid() ) { | ||
118 | // Draw our lines | ||
119 | int x2 = w - 1; | ||
120 | int y2 = h - 1; | ||
121 | QPen pen( p->pen() ); | ||
122 | p->setPen( colorGroup().mid() ); | ||
123 | p->drawLine( x2, 0, x2, y2 ); | ||
124 | p->drawLine( 0, y2, x2, y2 ); | ||
125 | p->setPen( pen ); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void DateBookDayView::paintFocus( QPainter *, const QRect & ) | ||
130 | { | ||
131 | } | ||
132 | |||
133 | |||
134 | void DateBookDayView::resizeEvent( QResizeEvent *e ) | ||
135 | { | ||
136 | QTable::resizeEvent( e ); | ||
137 | columnWidthChanged( 0 ); | ||
138 | emit sigColWidthChanged(); | ||
139 | } | ||
140 | |||
141 | void DateBookDayView::keyPressEvent( QKeyEvent *e ) | ||
142 | { | ||
143 | QString txt = e->text(); | ||
144 | if ( !txt.isNull() && txt[0] > ' ' && e->key() < 0x1000 ) { | ||
145 | // we this is some sort of thing we know about... | ||
146 | e->accept(); | ||
147 | emit sigCapturedKey( txt ); | ||
148 | } else { | ||
149 | // I don't know what this key is, do you? | ||
150 | e->ignore(); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | |||
155 | //=========================================================================== | ||
156 | |||
157 | DateBookDay::DateBookDay( bool ampm, bool startOnMonday, | ||
158 | DateBookDB *newDb, QWidget *parent, | ||
159 | const char *name ) | ||
160 | : QVBox( parent, name ), | ||
161 | currDate( QDate::currentDate() ), | ||
162 | db( newDb ), | ||
163 | startTime( 0 ) | ||
164 | { | ||
165 | widgetList.setAutoDelete( true ); | ||
166 | header = new DateBookDayHeader( startOnMonday, this, "day header" ); | ||
167 | header->setDate( currDate.year(), currDate.month(), currDate.day() ); | ||
168 | view = new DateBookDayView( ampm, this, "day view" ); | ||
169 | connect( header, SIGNAL( dateChanged( int, int, int ) ), | ||
170 | this, SLOT( dateChanged( int, int, int ) ) ); | ||
171 | connect( view, SIGNAL( sigColWidthChanged() ), | ||
172 | this, SLOT( slotColWidthChanged() ) ); | ||
173 | connect( qApp, SIGNAL(weekChanged(bool)), | ||
174 | this, SLOT(slotWeekChanged(bool)) ); | ||
175 | connect( view, SIGNAL(sigCapturedKey(const QString &)), | ||
176 | this, SIGNAL(sigNewEvent(const QString&)) ); | ||
177 | } | ||
178 | |||
179 | void DateBookDay::selectedDates( QDateTime &start, QDateTime &end ) | ||
180 | { | ||
181 | start.setDate( currDate ); | ||
182 | end.setDate( currDate ); | ||
183 | |||
184 | int sh=99,eh=-1; | ||
185 | |||
186 | int n = dayView()->numSelections(); | ||
187 | |||
188 | for (int i=0; i<n; i++) { | ||
189 | QTableSelection sel = dayView()->selection( i ); | ||
190 | sh = QMIN(sh,sel.topRow()); | ||
191 | eh = QMAX(sh,sel.bottomRow()+1); | ||
192 | } | ||
193 | if (sh > 23 || eh < 1) { | ||
194 | sh=8; | ||
195 | eh=9; | ||
196 | } | ||
197 | |||
198 | start.setTime( QTime( sh, 0, 0 ) ); | ||
199 | end.setTime( QTime( eh, 0, 0 ) ); | ||
200 | } | ||
201 | |||
202 | void DateBookDay::setDate( int y, int m, int d ) | ||
203 | { | ||
204 | header->setDate( y, m, d ); | ||
205 | } | ||
206 | |||
207 | void DateBookDay::setDate( QDate d) | ||
208 | { | ||
209 | header->setDate( d.year(), d.month(), d.day() ); | ||
210 | } | ||
211 | |||
212 | void DateBookDay::dateChanged( int y, int m, int d ) | ||
213 | { | ||
214 | QDate date( y, m, d ); | ||
215 | if ( currDate == date ) | ||
216 | return; | ||
217 | currDate.setYMD( y, m, d ); | ||
218 | relayoutPage(); | ||
219 | dayView()->clearSelection(); | ||
220 | QTableSelection ts; | ||
221 | ts.init( startTime, 0 ); | ||
222 | ts.expandTo( startTime, 0 ); | ||
223 | dayView()->addSelection( ts ); | ||
224 | } | ||
225 | |||
226 | void DateBookDay::redraw() | ||
227 | { | ||
228 | if ( isUpdatesEnabled() ) | ||
229 | relayoutPage(); | ||
230 | } | ||
231 | |||
232 | void DateBookDay::getEvents() | ||
233 | { | ||
234 | widgetList.clear(); | ||
235 | |||
236 | QValueList<EffectiveEvent> eventList = db->getEffectiveEvents( currDate, | ||
237 | currDate ); | ||
238 | QValueListIterator<EffectiveEvent> it; | ||
239 | for ( it = eventList.begin(); it != eventList.end(); ++it ) { | ||
240 | DateBookDayWidget* w = new DateBookDayWidget( *it, this ); | ||
241 | connect( w, SIGNAL( deleteMe( const Event & ) ), | ||
242 | this, SIGNAL( removeEvent( const Event & ) ) ); | ||
243 | connect( w, SIGNAL( editMe( const Event & ) ), | ||
244 | this, SIGNAL( editEvent( const Event & ) ) ); | ||
245 | connect( w, SIGNAL( beamMe( const Event & ) ), | ||
246 | this, SIGNAL( beamEvent( const Event & ) ) ); | ||
247 | widgetList.append( w ); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | static int place( const DateBookDayWidget *item, bool *used, int maxn ) | ||
252 | { | ||
253 | int place = 0; | ||
254 | int start = item->event().start().hour(); | ||
255 | QTime e = item->event().end(); | ||
256 | int end = e.hour(); | ||
257 | if ( e.minute() < 5 ) | ||
258 | end--; | ||
259 | if ( end < start ) | ||
260 | end = start; | ||
261 | while ( place < maxn ) { | ||
262 | bool free = TRUE; | ||
263 | int s = start; | ||
264 | while( s <= end ) { | ||
265 | if ( used[10*s+place] ) { | ||
266 | free = FALSE; | ||
267 | break; | ||
268 | } | ||
269 | s++; | ||
270 | } | ||
271 | if ( free ) break; | ||
272 | place++; | ||
273 | } | ||
274 | if ( place == maxn ) { | ||
275 | return -1; | ||
276 | } | ||
277 | while( start <= end ) { | ||
278 | used[10*start+place] = TRUE; | ||
279 | start++; | ||
280 | } | ||
281 | return place; | ||
282 | } | ||
283 | |||
284 | |||
285 | void DateBookDay::relayoutPage( bool fromResize ) | ||
286 | { | ||
287 | setUpdatesEnabled( FALSE ); | ||
288 | if ( !fromResize ) | ||
289 | getEvents(); // no need we already have them! | ||
290 | |||
291 | int wCount = widgetList.count(); | ||
292 | int wid = view->columnWidth(0)-1; | ||
293 | int n = 1; | ||
294 | |||
295 | if ( wCount < 20 ) { | ||
296 | for ( int i = 0; i < wCount; ) { | ||
297 | DateBookDayWidget *w = widgetList.at(i); | ||
298 | int x = 0; | ||
299 | int xp = 0; | ||
300 | QRect geom = w->geometry(); | ||
301 | geom.setX( x ); | ||
302 | geom.setWidth( wid ); | ||
303 | while ( xp < n && intersects( w, geom ) ) { | ||
304 | x += wid; | ||
305 | xp++; | ||
306 | geom.moveBy( wid, 0 ); | ||
307 | } | ||
308 | if ( xp >= n ) { | ||
309 | n++; | ||
310 | wid = ( view->columnWidth(0)-1 ) / n; | ||
311 | i = 0; | ||
312 | } else { | ||
313 | w->setGeometry( geom ); | ||
314 | i++; | ||
315 | } | ||
316 | } | ||
317 | view->setContentsPos( 0, startTime * view->rowHeight(0) ); | ||
318 | } else { | ||
319 | |||
320 | |||
321 | int hours[24]; | ||
322 | memset( hours, 0, 24*sizeof( int ) ); | ||
323 | bool overFlow = FALSE; | ||
324 | for ( int i = 0; i < wCount; i++ ) { | ||
325 | DateBookDayWidget *w = widgetList.at(i); | ||
326 | int start = w->event().start().hour(); | ||
327 | QTime e = w->event().end(); | ||
328 | int end = e.hour(); | ||
329 | if ( e.minute() < 5 ) | ||
330 | end--; | ||
331 | if ( end < start ) | ||
332 | end = start; | ||
333 | while( start <= end ) { | ||
334 | hours[start]++; | ||
335 | if ( hours[start] >= 10 ) | ||
336 | overFlow = TRUE; | ||
337 | ++start; | ||
338 | } | ||
339 | if ( overFlow ) | ||
340 | break; | ||
341 | } | ||
342 | for ( int i = 0; i < 24; i++ ) { | ||
343 | n = QMAX( n, hours[i] ); | ||
344 | } | ||
345 | wid = ( view->columnWidth(0)-1 ) / n; | ||
346 | |||
347 | bool used[24*10]; | ||
348 | memset( used, FALSE, 24*10*sizeof( bool ) ); | ||
349 | |||
350 | for ( int i = 0; i < wCount; i++ ) { | ||
351 | DateBookDayWidget *w = widgetList.at(i); | ||
352 | int xp = place( w, used, n ); | ||
353 | if ( xp != -1 ) { | ||
354 | QRect geom = w->geometry(); | ||
355 | geom.setX( xp*wid ); | ||
356 | geom.setWidth( wid ); | ||
357 | w->setGeometry( geom ); | ||
358 | } | ||
359 | } | ||
360 | view->setContentsPos( 0, startTime * view->rowHeight(0) ); | ||
361 | } | ||
362 | setUpdatesEnabled( TRUE ); | ||
363 | return; | ||
364 | } | ||
365 | |||
366 | DateBookDayWidget *DateBookDay::intersects( const DateBookDayWidget *item, const QRect &geom ) | ||
367 | { | ||
368 | int i = 0; | ||
369 | DateBookDayWidget *w = widgetList.at(i); | ||
370 | int wCount = widgetList.count(); | ||
371 | while ( i < wCount && w != item ) { | ||
372 | if ( w->geometry().intersects( geom ) ) { | ||
373 | return w; | ||
374 | } | ||
375 | w = widgetList.at(++i); | ||
376 | } | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | |||
382 | QDate DateBookDay::date() const | ||
383 | { | ||
384 | return currDate; | ||
385 | } | ||
386 | |||
387 | void DateBookDay::setStartViewTime( int startHere ) | ||
388 | { | ||
389 | startTime = startHere; | ||
390 | dayView()->clearSelection(); | ||
391 | QTableSelection ts; | ||
392 | ts.init( startTime, 0 ); | ||
393 | ts.expandTo( startTime, 0 ); | ||
394 | dayView()->addSelection( ts ); | ||
395 | } | ||
396 | |||
397 | int DateBookDay::startViewTime() const | ||
398 | { | ||
399 | return startTime; | ||
400 | } | ||
401 | |||
402 | void DateBookDay::slotWeekChanged( bool bStartOnMonday ) | ||
403 | { | ||
404 | header->setStartOfWeek( bStartOnMonday ); | ||
405 | // redraw(); | ||
406 | } | ||
407 | |||
408 | void DateBookDay::keyPressEvent(QKeyEvent *e) | ||
409 | { | ||
410 | switch(e->key()) { | ||
411 | case Key_Up: | ||
412 | view->moveUp(); | ||
413 | break; | ||
414 | case Key_Down: | ||
415 | view->moveDown(); | ||
416 | break; | ||
417 | case Key_Left: | ||
418 | setDate(QDate(currDate).addDays(-1)); | ||
419 | break; | ||
420 | case Key_Right: | ||
421 | setDate(QDate(currDate).addDays(1)); | ||
422 | break; | ||
423 | default: | ||
424 | e->ignore(); | ||
425 | } | ||
426 | } | ||
427 | |||
428 | //=========================================================================== | ||
429 | |||
430 | DateBookDayWidget::DateBookDayWidget( const EffectiveEvent &e, | ||
431 | DateBookDay *db ) | ||
432 | : QWidget( db->dayView()->viewport() ), ev( e ), dateBook( db ) | ||
433 | { | ||
434 | bool whichClock = db->dayView()->whichClock(); | ||
435 | |||
436 | // why would someone use "<"? Oh well, fix it up... | ||
437 | // I wonder what other things may be messed up... | ||
438 | QString strDesc = ev.description(); | ||
439 | int where = strDesc.find( "<" ); | ||
440 | while ( where != -1 ) { | ||
441 | strDesc.remove( where, 1 ); | ||
442 | strDesc.insert( where, "<" ); | ||
443 | where = strDesc.find( "<", where ); | ||
444 | } | ||
445 | |||
446 | QString strCat; | ||
447 | // ### Fix later... | ||
448 | // QString strCat = ev.category(); | ||
449 | // where = strCat.find( "<" ); | ||
450 | // while ( where != -1 ) { | ||
451 | // strCat.remove( where, 1 ); | ||
452 | // strCat.insert( where, "<" ); | ||
453 | // where = strCat.find( "<", where ); | ||
454 | // } | ||
455 | |||
456 | QString strNote = ev.notes(); | ||
457 | where = strNote.find( "<" ); | ||
458 | while ( where != -1 ) { | ||
459 | strNote.remove( where, 1 ); | ||
460 | strNote.insert( where, "<" ); | ||
461 | where = strNote.find( "<", where ); | ||
462 | } | ||
463 | |||
464 | text = "<b>" + strDesc + "</b><br>" + "<i>" | ||
465 | + strCat + "</i>" | ||
466 | + "<br><b>" + tr("Start") + "</b>: "; | ||
467 | |||
468 | |||
469 | if ( e.startDate() != ev.date() ) { | ||
470 | // multi-day event. Show start date | ||
471 | text += TimeString::longDateString( e.startDate() ); | ||
472 | } else { | ||
473 | // Show start time. | ||
474 | text += TimeString::timeString( ev.start(), whichClock, FALSE ); | ||
475 | } | ||
476 | |||
477 | text += "<br><b>" + tr("End") + "</b>: "; | ||
478 | if ( e.endDate() != ev.date() ) { | ||
479 | // multi-day event. Show end date | ||
480 | text += TimeString::longDateString( e.endDate() ); | ||
481 | } else { | ||
482 | // Show end time. | ||
483 | text += TimeString::timeString( ev.end(), whichClock, FALSE ); | ||
484 | } | ||
485 | text += "<br><br>" + strNote; | ||
486 | setBackgroundMode( PaletteBase ); | ||
487 | |||
488 | QTime s = ev.start(); | ||
489 | QTime e = ev.end(); | ||
490 | int y = s.hour()*60+s.minute(); | ||
491 | int h = e.hour()*60+e.minute()-y; | ||
492 | int rh = dateBook->dayView()->rowHeight(0); | ||
493 | y = y*rh/60; | ||
494 | h = h*rh/60; | ||
495 | if ( h < 3 ) | ||
496 | h = 3; | ||
497 | geom.setY( y ); | ||
498 | geom.setHeight( h ); | ||
499 | } | ||
500 | |||
501 | DateBookDayWidget::~DateBookDayWidget() | ||
502 | { | ||
503 | } | ||
504 | |||
505 | void DateBookDayWidget::paintEvent( QPaintEvent *e ) | ||
506 | { | ||
507 | QPainter p( this ); | ||
508 | p.setPen( QColor(100, 100, 100) ); | ||
509 | p.setBrush( QColor( 255, 240, 230 ) ); // based on priority? | ||
510 | p.drawRect(rect()); | ||
511 | |||
512 | int y = 0; | ||
513 | int d = 0; | ||
514 | |||
515 | if ( ev.event().hasAlarm() ) { | ||
516 | p.drawPixmap( width() - 16, 0, Resource::loadPixmap( "bell" ) ); | ||
517 | y = 20; | ||
518 | d = 20; | ||
519 | } | ||
520 | |||
521 | if ( ev.event().hasRepeat() ) { | ||
522 | p.drawPixmap( width() - 16, y, Resource::loadPixmap( "repeat" ) ); | ||
523 | d = 20; | ||
524 | } | ||
525 | |||
526 | QSimpleRichText rt( text, font() ); | ||
527 | rt.setWidth( geom.width() - d - 6 ); | ||
528 | rt.draw( &p, 3, 0, e->region(), colorGroup() ); | ||
529 | } | ||
530 | |||
531 | void DateBookDayWidget::mousePressEvent( QMouseEvent *e ) | ||
532 | { | ||
533 | QPopupMenu m; | ||
534 | m.insertItem( tr( "Edit" ), 1 ); | ||
535 | m.insertItem( tr( "Delete" ), 2 ); | ||
536 | m.insertItem( tr( "Beam" ), 3 ); | ||
537 | int r = m.exec( e->globalPos() ); | ||
538 | if ( r == 1 ) { | ||
539 | emit editMe( ev.event() ); | ||
540 | } else if ( r == 2 ) { | ||
541 | emit deleteMe( ev.event() ); | ||
542 | } else if ( r == 3 ) { | ||
543 | emit beamMe( ev.event() ); | ||
544 | } | ||
545 | } | ||
546 | |||
547 | void DateBookDayWidget::setGeometry( const QRect &r ) | ||
548 | { | ||
549 | geom = r; | ||
550 | setFixedSize( r.width()+1, r.height()+1 ); | ||
551 | dateBook->dayView()->moveChild( this, r.x(), r.y()-1 ); | ||
552 | show(); | ||
553 | } | ||