summaryrefslogtreecommitdiff
path: root/core/pim/todo/todotable.cpp
Unidiff
Diffstat (limited to 'core/pim/todo/todotable.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/pim/todo/todotable.cpp949
1 files changed, 0 insertions, 949 deletions
diff --git a/core/pim/todo/todotable.cpp b/core/pim/todo/todotable.cpp
deleted file mode 100644
index 15f733b..0000000
--- a/core/pim/todo/todotable.cpp
+++ b/dev/null
@@ -1,949 +0,0 @@
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/* Show Deadline was added by Stefan Eilers (se, eilers.stefan@epost.de)
21 */
22#include "todotable.h"
23
24#include <opie/tododb.h>
25#include <opie/xmltree.h>
26
27#include <qpe/categoryselect.h>
28#include <qpe/xmlreader.h>
29
30#include <qasciidict.h>
31#include <qcombobox.h>
32#include <qfile.h>
33#include <qpainter.h>
34#include <qtextcodec.h>
35#include <qtimer.h>
36#include <qdatetime.h>
37#include <qtextstream.h>
38
39#include <qcursor.h>
40#include <qregexp.h>
41
42#include <errno.h>
43#include <stdlib.h>
44
45#include <stdio.h>
46
47using namespace Opie;
48
49namespace {
50
51 static bool taskCompare( const ToDoEvent &task, const QRegExp &r, int category );
52 static QString journalFileName();
53 static ToDoEvent xmlToEvent( XMLElement *ev );
54}
55CheckItem::CheckItem( QTable *t, const QString &key )
56 : QTableItem( t, Never, "" ), checked( FALSE ), sortKey( key )
57{
58}
59
60QString CheckItem::key() const
61{
62 return sortKey;
63}
64
65void CheckItem::setChecked( bool b )
66{
67 checked = b;
68 table()->updateCell( row(), col() );
69}
70
71void CheckItem::toggle()
72{
73 TodoTable *parent = static_cast<TodoTable*>(table());
74 ToDoEvent newTodo = parent->currentEntry();
75 checked = !checked;
76 newTodo.setCompleted( checked );
77 table()->updateCell( row(), col() );
78 parent->replaceCurrentEntry( newTodo, true );
79}
80
81bool CheckItem::isChecked() const
82{
83 return checked;
84}
85
86static const int BoxSize = 10;
87
88void CheckItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr,
89 bool )
90{
91 p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) );
92
93 int marg = ( cr.width() - BoxSize ) / 2;
94 int x = 0;
95 int y = ( cr.height() - BoxSize ) / 2;
96 p->setPen( QPen( cg.text() ) );
97 p->drawRect( x + marg, y, BoxSize, BoxSize );
98 p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 );
99 p->setPen( darkGreen );
100 x += 1;
101 y += 1;
102 if ( checked ) {
103 QPointArray a( 7*2 );
104 int i, xx, yy;
105 xx = x+1+marg;
106 yy = y+2;
107 for ( i=0; i<3; i++ ) {
108 a.setPoint( 2*i, xx, yy );
109 a.setPoint( 2*i+1, xx, yy+2 );
110 xx++; yy++;
111 }
112 yy -= 2;
113 for ( i=3; i<7; i++ ) {
114 a.setPoint( 2*i, xx, yy );
115 a.setPoint( 2*i+1, xx, yy+2 );
116 xx++; yy--;
117 }
118 p->drawLineSegments( a );
119 }
120}
121
122
123ComboItem::ComboItem( QTable *t, EditType et )
124 : QTableItem( t, et, "3" ), cb( 0 )
125{
126 setReplaceable( FALSE );
127}
128
129QWidget *ComboItem::createEditor() const
130{
131 QString txt = text();
132 ( (ComboItem*)this )->cb = new QComboBox( table()->viewport() );
133 cb->insertItem( "1" );
134 cb->insertItem( "2" );
135 cb->insertItem( "3" );
136 cb->insertItem( "4" );
137 cb->insertItem( "5" );
138 cb->setCurrentItem( txt.toInt() - 1 );
139 return cb;
140}
141
142void ComboItem::setContentFromEditor( QWidget *w )
143{
144 TodoTable *parent = static_cast<TodoTable*>(table());
145 ToDoEvent newTodo = parent->currentEntry();
146
147 if ( w->inherits( "QComboBox" ) )
148 setText( ( (QComboBox*)w )->currentText() );
149 else
150 QTableItem::setContentFromEditor( w );
151 newTodo.setPriority( text().toInt() );
152 parent->replaceCurrentEntry( newTodo, true );
153}
154
155void ComboItem::setText( const QString &s )
156{
157 if ( cb )
158 cb->setCurrentItem( s.toInt() - 1 );
159 QTableItem::setText( s );
160}
161
162QString ComboItem::text() const
163{
164 if ( cb )
165 return cb->currentText();
166 return QTableItem::text();
167}
168DueTextItem::DueTextItem( QTable *t, ToDoEvent *ev )
169 : QTableItem(t, Never, QString::null )
170{
171 setToDoEvent( ev );
172}
173QString DueTextItem::key() const
174{
175 QString key;
176 if( m_hasDate ){
177 if(m_off == 0 ){
178 key.append("b");
179 }else if( m_off > 0 ){
180 key.append("c");
181 }else if( m_off < 0 ){
182 key.append("a");
183 }
184 key.append(QString::number(m_off ) );
185 }else{
186 key.append("d");
187 }
188 return key;
189}
190void DueTextItem::setToDoEvent( const ToDoEvent *ev )
191{
192 m_hasDate = ev->hasDate();
193 m_completed = ev->isCompleted();
194 if( ev->hasDate() ){
195 QDate today = QDate::currentDate();
196 m_off = today.daysTo(ev->date() );
197 //qWarning("DueText m_off=%d", m_off );
198 setText( QString::number(m_off) + " day(s) " );
199 }else{
200 setText("n.d." );
201 m_off = 0;
202 }
203 //qWarning("m_off=%d", m_off );
204}
205void DueTextItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected )
206{
207 //qWarning ("paint m_off=%d", m_off );
208 QColorGroup cg2(cg);
209 QColor text = cg.text();
210 if( m_hasDate && !m_completed ){
211 if( m_off < 0 ){
212 cg2.setColor(QColorGroup::Text, QColor(red ) );
213 }else if( m_off == 0 ){
214 cg2.setColor(QColorGroup::Text, QColor(yellow) ); // orange isn't predefined
215 }else if( m_off > 0){
216 cg2.setColor(QColorGroup::Text, QColor(green ) );
217 }
218 }
219 QTableItem::paint(p, cg2, cr, selected );
220 cg2.setColor(QColorGroup::Text, text );
221}
222TodoTable::TodoTable( QWidget *parent, const char *name )
223// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR
224// : QTable( 0, 3, parent, name, TRUE ),
225// #else
226 : QTable( 0, 4, parent, name ),
227// #endif
228 showComp( true ),
229 enablePainting( true ),
230 mCat( 0 ),
231 currFindRow( -2 ),
232 showDeadl( true)
233{
234 setNumRows(0);
235 mCat.load( categoryFileName() );
236 setSorting( TRUE );
237 setSelectionMode( NoSelection );
238 setColumnStretchable( 2, TRUE );
239 setColumnWidth( 0, 20 );
240 setColumnWidth( 1, 35 );
241
242 setLeftMargin( 0 );
243 verticalHeader()->hide();
244 horizontalHeader()->setLabel( 0, tr( "C." ) );
245 horizontalHeader()->setLabel( 1, tr( "Prior." ) );
246 horizontalHeader()->setLabel( 2, tr( "Description" ) );
247
248 setColumnStretchable( 3, FALSE );
249 setColumnWidth( 3, 20 );
250 horizontalHeader()->setLabel( 3, tr( "Deadline" ) );
251
252 if (showDeadl){
253 showColumn (3);
254 }else{
255 hideColumn (3);
256 }
257
258 connect( this, SIGNAL( clicked( int, int, int, const QPoint & ) ),
259 this, SLOT( slotClicked( int, int, int, const QPoint & ) ) );
260 connect( this, SIGNAL( pressed( int, int, int, const QPoint & ) ),
261 this, SLOT( slotPressed( int, int, int, const QPoint & ) ) );
262 connect( this, SIGNAL( valueChanged( int, int ) ),
263 this, SLOT( slotCheckPriority( int, int ) ) );
264 connect( this, SIGNAL( currentChanged( int, int ) ),
265 this, SLOT( slotCurrentChanged( int, int ) ) );
266
267 menuTimer = new QTimer( this );
268 connect( menuTimer, SIGNAL(timeout()), this, SLOT(slotShowMenu()) );
269
270 mDayTimer = new QTimer( this );
271 connect( mDayTimer, SIGNAL(timeout()), this, SLOT(slotCheckDay() ) );
272 mDay = QDate::currentDate();
273}
274
275void TodoTable::addEntry( const ToDoEvent &todo )
276{
277 int row = numRows();
278 setNumRows( row + 1 );
279 updateJournal( todo, ACTION_ADD );
280 insertIntoTable( new ToDoEvent(todo), row );
281 setCurrentCell(row, currentColumn());
282 updateVisible();
283}
284
285void TodoTable::slotClicked( int row, int col, int, const QPoint &pos )
286{
287 if ( !cellGeometry( row, col ).contains(pos) )
288 return;
289 // let's switch on the column number...
290 switch ( col )
291 {
292 case 0: {
293 CheckItem *i = static_cast<CheckItem*>(item( row, col ));
294 if ( i ) {
295 int x = pos.x() - columnPos( col );
296 int y = pos.y() - rowPos( row );
297 int w = columnWidth( col );
298 int h = rowHeight( row );
299 if ( i && x >= ( w - BoxSize ) / 2 && x <= ( w - BoxSize ) / 2 + BoxSize &&
300 y >= ( h - BoxSize ) / 2 && y <= ( h - BoxSize ) / 2 + BoxSize ) {
301 i->toggle();
302 }
303 emit signalDoneChanged( i->isChecked() );
304 }
305 }
306 break;
307 case 1:
308 break;
309 case 2:
310 // Show detailed view of the selected entry
311 {
312 menuTimer->stop();
313 ToDoEvent *todo = todoList[static_cast<CheckItem*>(item(row, 0))];
314 emit showDetails( *todo );
315 }
316 break;
317 case 3:
318 // may as well edit it...
319 menuTimer->stop();
320 emit signalEdit();
321 break;
322 }
323}
324
325void TodoTable::slotPressed( int row, int col, int, const QPoint &pos )
326{
327 if ( col == 2 && cellGeometry( row, col ).contains(pos) )
328 menuTimer->start( 750, TRUE );
329}
330
331void TodoTable::slotShowMenu()
332{
333 emit signalShowMenu( QCursor::pos() );
334}
335
336void TodoTable::slotCurrentChanged( int, int )
337{
338 menuTimer->stop();
339}
340
341void TodoTable::internalAddEntries( QList<ToDoEvent> &list )
342{
343 setNumRows( list.count() );
344 int row = 0;
345 ToDoEvent *it;
346 for ( it = list.first(); it; it = list.next() )
347 insertIntoTable( it, row++ );
348}
349
350
351ToDoEvent TodoTable::currentEntry() const
352{
353 //qWarning ("in currentEntry\n");
354
355 QTableItem *i = item( currentRow(), 0 );
356 if ( !i || rowHeight( currentRow() ) <= 0 )
357 return ToDoEvent();
358 ToDoEvent *todo = todoList[(CheckItem*)i];
359 todo->setCompleted( ( (CheckItem*)item( currentRow(), 0 ) )->isChecked() );
360 todo->setPriority( ( (ComboItem*)item( currentRow(), 1 ) )->text().toInt() );
361 return *todo;
362}
363
364void TodoTable::replaceCurrentEntry( const ToDoEvent &todo, bool fromTableItem )
365{
366 int row = currentRow();
367 updateJournal( todo, ACTION_REPLACE);
368
369 if ( !fromTableItem ) {
370 journalFreeReplaceEntry( todo, row );
371 updateVisible();
372 }
373}
374
375void TodoTable::removeCurrentEntry()
376{
377 ToDoEvent *oldTodo;
378 int row = currentRow();
379 CheckItem *chk;
380
381 chk = static_cast<CheckItem*>(item(row, 0 ));
382 if ( !chk )
383 return;
384 oldTodo = todoList[chk];
385 todoList.remove( chk );
386 oldTodo->setCompleted( chk->isChecked() );
387 oldTodo->setPriority( static_cast<ComboItem*>(item(row, 1))->text().toInt() );
388 realignTable( row );
389 updateVisible();
390 updateJournal( *oldTodo, ACTION_REMOVE);
391 delete oldTodo;
392}
393
394
395bool TodoTable::save( const QString &fn )
396{
397 QString strNewFile = fn + ".new";
398 QFile::remove( strNewFile ); // just to be sure
399 ToDoDB todoDB( strNewFile );
400 for ( QMap<CheckItem*, ToDoEvent *>::Iterator it = todoList.begin();
401 it != todoList.end(); ++it ) {
402 if ( !item( it.key()->row(), 0 ) )
403 continue;
404 ToDoEvent *todo = *it;
405 // sync item with table
406 todo->setCompleted( ((CheckItem*)item(it.key()->row(), 0))->isChecked() );
407 todo->setPriority( ((ComboItem*)item( it.key()->row(), 1))->text().toInt() );
408 todoDB.addEvent( *todo );
409 }
410 if(!todoDB.save() ){
411 QFile::remove( strNewFile );
412 return false;
413 };
414 // now do the rename
415 if ( ::rename( strNewFile, fn ) < 0 )
416 qWarning( "problem renaming file %s to %s errno %d",
417 strNewFile.latin1(), fn.latin1(), errno );
418
419 // remove the journal
420 QFile::remove( journalFileName() );
421 return true;
422}
423
424void TodoTable::load( const QString &fn )
425{
426 if ( QFile::exists(journalFileName()) ) {
427 applyJournal();
428 QFile::remove(journalFileName() );
429 }
430 loadFile( fn );
431// QTable::sortColumn(2,TRUE,TRUE);
432// QTable::sortColumn(1,TRUE,TRUE);
433 QTable::sortColumn(0,TRUE,TRUE);
434 setCurrentCell( 0, 2 );
435 setSorting(true );
436 mDayTimer->start( 60 * 1000 ); // gone in 60 seconds?
437}
438void TodoTable::updateVisible()
439{
440 if ( !isUpdatesEnabled() )
441 return;
442
443 if (showDeadl){
444 showColumn (3);
445 adjustColumn(3);
446 }else{
447 hideColumn (3);
448 adjustColumn(2);
449 }
450
451 int visible = 0;
452 int id = mCat.id( "Todo List", showCat );
453 for ( int row = 0; row < numRows(); row++ ) {
454 CheckItem *ci = (CheckItem *)item( row, 0 );
455 ToDoEvent *t = todoList[ci];
456 if (!t)
457 continue;
458
459 QArray<int> vlCats = t->categories();
460 bool hide = false;
461 if ( !showComp && ci->isChecked() )
462 hide = true;
463 if ( !showCat.isEmpty() ) {
464 if ( showCat == tr( "Unfiled" ) ) {
465 if ( vlCats.count() > 0 )
466 hide = true;
467 } else {
468 // do some comparing, we have to reverse our idea here... which idea? - zecke
469 if ( !hide ) {
470 hide = true;
471 for ( uint it = 0; it < vlCats.count(); ++it ) {
472 if ( vlCats[it] == id ) {
473 hide = false;
474 break;
475 }
476 }
477 }
478 }
479 }
480 if ( hide ) {
481 if ( currentRow() == row )
482 setCurrentCell( -1, 0 );
483 if ( rowHeight( row ) > 0 )
484 hideRow( row );
485 } else {
486 if ( rowHeight( row ) == 0 ) {
487 showRow( row );
488 adjustRow( row );
489 }
490 visible++;
491 }
492 }
493 if ( !visible )
494 setCurrentCell( -1, 0 );
495}
496
497void TodoTable::viewportPaintEvent( QPaintEvent *pe )
498{
499 if ( enablePainting )
500 QTable::viewportPaintEvent( pe );
501}
502
503void TodoTable::setPaintingEnabled( bool e )
504{
505 if ( e != enablePainting ) {
506 if ( !enablePainting ) {
507 enablePainting = true;
508 rowHeightChanged( 0 );
509 viewport()->update();
510 } else {
511 enablePainting = false;
512 }
513 }
514}
515
516void TodoTable::clear()
517{
518 for ( QMap<CheckItem*, ToDoEvent *>::Iterator it = todoList.begin();
519 it != todoList.end(); ++it ) {
520 ToDoEvent *todo = it.data();
521 updateJournal( *todo, ACTION_REMOVE );
522 delete todo;
523 }
524 todoList.clear();
525 for ( int r = 0; r < numRows(); ++r ) {
526 for ( int c = 0; c < numCols(); ++c ) {
527 if ( cellWidget( r, c ) )
528 clearCellWidget( r, c );
529 clearCell( r, c );
530 }
531 }
532 setNumRows( 0 );
533}
534
535void TodoTable::sortColumn( int col, bool ascending, bool /*wholeRows*/ )
536{
537 // The default for wholeRows is false, however
538 // for this todo table we want to exchange complete
539 // rows when sorting. Also, we always want ascending, since
540 // the values have a logical order.
541 QTable::sortColumn( col, ascending, TRUE );
542 updateVisible();
543}
544
545void TodoTable::slotCheckPriority(int row, int col )
546{
547 // kludgey work around to make forward along the updated priority...
548 if ( col == 1 ) {
549 // let everyone know!!
550 ComboItem* i = static_cast<ComboItem*>( item( row, col ) );
551 emit signalPriorityChanged( i->text().toInt() );
552 }
553}
554
555
556void TodoTable::updateJournal( const ToDoEvent &todo, journal_action action )
557{
558 QFile f( journalFileName() );
559 if ( !f.open(IO_WriteOnly|IO_Append) )
560 return;
561 QString buf;
562 QCString str;
563 buf = "<Task";
564 // todo.save( buf );
565 buf += " Action=\"" + QString::number( int(action) ) + "\"";
566 buf += " Uid=\"" + QString::number( todo.uid() ) + "\""; // better write the id
567 buf += " Completed=\""+ QString::number((int)todo.isCompleted() ) + "\"";
568 buf += " HasDate=\""+ QString::number((int)todo.hasDate() ) +"\"";
569 buf += " Priority=\"" + QString::number( todo.priority() ) + "\"";
570 QArray<int> arrat = todo.categories();
571 QString attr;
572 for(uint i=0; i < arrat.count(); i++ ){
573 attr.append(QString::number(arrat[i])+";" );
574 }
575 if(!attr.isEmpty() ) // remove the last ;
576 attr.remove(attr.length()-1, 1 );
577 buf += " Categories=\"" + attr + "\"";
578 buf += " Description=\"" + todo.description() + "\"";
579 buf += " Summary=\"" + todo.summary() + "\"";
580 if(todo.hasDate() ) {
581 buf += " DateYear=\""+QString::number( todo.date().year() ) + "\"";
582 buf += " DateMonth=\"" + QString::number( todo.date().month() ) + "\"";
583 buf += " DateDay=\"" + QString::number( todo.date().day() ) + "\"";
584 }
585 buf += "/>\n";
586 str = buf.utf8();
587 f.writeBlock( str.data(), str.length() );
588 f.close();
589}
590
591void TodoTable::rowHeightChanged( int row )
592{
593 if ( enablePainting )
594 QTable::rowHeightChanged( row );
595}
596
597void TodoTable::loadFile( const QString &/*we use the standard*/ )
598{
599
600 QList<ToDoEvent> list;
601 ToDoDB todoDB;
602 QValueList<ToDoEvent> vaList = todoDB.rawToDos();
603 for(QValueList<ToDoEvent>::ConstIterator it = vaList.begin(); it != vaList.end(); ++it ){
604 ToDoEvent *event = new ToDoEvent( (*it) );
605 list.append( event );
606 }
607 vaList.clear();
608 // qDebug("parsing done=%d", t.elapsed() );
609 if ( list.count() > 0 ) {
610 internalAddEntries( list );
611 list.clear();
612 }
613// qDebug("loading done: t=%d", t.elapsed() );
614}
615
616void TodoTable::journalFreeReplaceEntry( const ToDoEvent &todo, int row )
617{
618 QString strTodo = todo.summary();
619 if( strTodo.isEmpty() ){
620 strTodo = todo.description().left(40).simplifyWhiteSpace();
621 //todo.setSummary(strTodo );
622 }
623 if ( row == -1 ) {
624 QMapIterator<CheckItem*, ToDoEvent *> it;
625 for ( it = todoList.begin(); it != todoList.end(); ++it ) {
626 if ( *(*it) == todo ) {
627 row = it.key()->row();
628 it.key()->setChecked( todo.isCompleted() );
629 static_cast<ComboItem*>(item(row, 1))->setText( QString::number(todo.priority()) );
630 item( row, 2 )->setText( strTodo );
631
632 if (showDeadl){
633 static_cast<DueTextItem*>(item(row,3))->setToDoEvent(&todo );
634 }
635
636 *(*it) = todo;
637 }
638 }
639 } else {
640 ToDoEvent *t = todoList[static_cast<CheckItem*>(item(row, 0))];
641 todoList.remove( static_cast<CheckItem*>(item(row, 0)) );
642 delete t;
643 static_cast<CheckItem*>(item(row, 0))->setChecked( todo.isCompleted() );
644 static_cast<ComboItem*>(item(row, 1))->setText( QString::number(todo.priority()) );
645 item( row, 2 )->setText( strTodo );
646
647 if (showDeadl){
648 static_cast<DueTextItem*>(item(row,3))->setToDoEvent(&todo );
649 }
650 todoList.insert( static_cast<CheckItem*>(item(row,0)), new ToDoEvent(todo) );
651 }
652}
653
654void TodoTable::journalFreeRemoveEntry( int row )
655{
656 CheckItem *chk;
657 chk = static_cast<CheckItem*>(item(row, 0 ));
658 if ( !chk )
659 return;
660 todoList.remove( chk );
661
662 realignTable( row );
663}
664
665void TodoTable::keyPressEvent( QKeyEvent *e )
666{
667 if ( e->key() == Key_Space || e->key() == Key_Return ) {
668 switch ( currentColumn() ) {
669 case 0: {
670 CheckItem *i = static_cast<CheckItem*>(item(currentRow(),
671 currentColumn()));
672 if ( i )
673 i->toggle();
674 break;
675 }
676 case 1:
677 break;
678 case 2:{
679 ToDoEvent *todo = todoList[static_cast<CheckItem*>(item(currentRow(), 0))];
680 emit showDetails(*todo);
681 break;
682 }
683 case 3:
684 // Future: Let us change the dueDate directly...
685 emit signalEdit();
686 default:
687 break;
688 }
689 } else
690 QTable::keyPressEvent( e );
691}
692
693
694QStringList TodoTable::categories()
695{
696 // This is called seldom, so calling a load in here
697 // should be fine.
698 mCat.load( categoryFileName() );
699 QStringList categoryList = mCat.labels( "Todo List" );
700 return categoryList;
701}
702
703void TodoTable::slotDoFind( const QString &findString, bool caseSensitive,
704 bool backwards, int category )
705{
706 // we have to iterate through the table, this gives the illusion that
707 // sorting is actually being used.
708 if ( currFindRow < -1 )
709 currFindRow = currentRow() - 1;
710 clearSelection( TRUE );
711 int rows,
712 row;
713 CheckItem *chk;
714 QRegExp r( findString );
715
716 r.setCaseSensitive( caseSensitive );
717 rows = numRows();
718 static bool wrapAround = true;
719
720 if ( !backwards ) {
721 for ( row = currFindRow + 1; row < rows; row++ ) {
722 chk = static_cast<CheckItem*>( item(row, 0) );
723 if ( taskCompare(*(todoList[chk]), r, category) )
724 break;
725 }
726 } else {
727 for ( row = currFindRow - 1; row > -1; row-- ) {
728 chk = static_cast<CheckItem*>( item(row, 0) );
729 if ( taskCompare(*(todoList[chk]), r, category) )
730 break;
731 }
732 }
733 if ( row >= rows || row < 0 ) {
734 if ( row < 0 )
735 currFindRow = rows;
736 else
737 currFindRow = -1;
738 if ( wrapAround )
739 emit signalWrapAround();
740 else
741 emit signalNotFound();
742 wrapAround = !wrapAround;
743 } else {
744 currFindRow = row;
745 QTableSelection foundSelection;
746 foundSelection.init( currFindRow, 0 );
747 foundSelection.expandTo( currFindRow, numCols() - 1 );
748 addSelection( foundSelection );
749 setCurrentCell( currFindRow, numCols() - 1 );
750 // we should always be able to wrap around and find this again,
751 // so don't give confusing not found message...
752 wrapAround = true;
753 }
754}
755
756int TodoTable::showCategoryId() const
757{
758 int id;
759 id = -1;
760 // if allcategories are selected, you get unfiled...
761 if ( showCat != tr( "Unfiled" ) && showCat != tr( "All" ) )
762 id = mCat.id( "Todo List", showCat );
763 return id;
764}
765void TodoTable::applyJournal()
766{
767 // we need to hack
768 QFile file( journalFileName() );
769 if( file.open(IO_ReadOnly ) ) {
770 QByteArray ar = file.readAll();
771 file.close();
772 QFile file2( journalFileName() + "_new" );
773 if( file2.open(IO_WriteOnly ) ){
774 QTextStream str(&file2 );
775 str << QString::fromLatin1("<Tasks>") << endl;
776 str << ar.data();
777 str << QString::fromLatin1("</Tasks>") << endl;
778 file2.close();
779 }
780 XMLElement *root = XMLElement::load(journalFileName()+ "_new");
781 XMLElement *el = root->firstChild();
782 el = el->firstChild();
783 ToDoDB tododb; // allready loaded ;)
784 bool ok;
785 int action;
786 QString dummy;
787 while( el ){
788 dummy = el->attribute("Action" );
789 action = dummy.toInt(&ok );
790 ToDoEvent ev = xmlToEvent( el );
791 if(ok ){
792 switch( action){
793 case ACTION_ADD:
794 tododb.addEvent(ev );
795 break;
796 case ACTION_REMOVE:
797 tododb.removeEvent( ev );
798 break;
799 case ACTION_REPLACE:
800 tododb.replaceEvent( ev );
801 break;
802 }
803 }
804 el = el->nextChild();
805 }
806 QFile::remove(journalFileName()+ "_new" );
807 tododb.save();
808 }
809}
810void TodoTable::slotCheckDay()
811{
812 QDate date = QDate::currentDate();
813 if( mDay.daysTo(date )!= 0 ){
814 setPaintingEnabled( FALSE );
815 for(int i=0; i < numRows(); i++ ){
816 ToDoEvent *t = todoList[static_cast<CheckItem*>(item(i, 0))];
817 static_cast<DueTextItem*>(item(i, 3) )->setToDoEvent( t );
818
819 }
820 setPaintingEnabled( TRUE );
821 mDay = date;
822 }
823 mDayTimer->start( 60 * 1000 ); // 60 seconds
824}
825// check Action and decide
826/*
827void TodoTable::doApply(XMLElement *el )
828{
829 QString dummy;
830 bool ok;
831 int action;
832 dummy = el->attribute("Action" );
833 action = dummy.toInt(&ok );
834 ToDoEvent ev = xmlToEvent( el );
835 if( ok ){
836 switch( action ){
837 case ACTION_ADD:
838 addEntry( ev );
839 break;
840 case ACTION_REMOVE:{ // find an entry with the same uid and remove it then
841 break;
842 }
843 case ACTION_REPLACE:
844 break;
845 }
846 }
847}
848*/
849namespace {
850static bool taskCompare( const ToDoEvent &task, const QRegExp &r, int category )
851{
852 bool returnMe;
853 QArray<int> cats;
854 cats = task.categories();
855
856 returnMe = false;
857 if ( (category == -1 && cats.count() == 0) || category == -2 )
858 returnMe = task.match( r );
859 else {
860 int i;
861 for ( i = 0; i < int(cats.count()); i++ ) {
862 if ( cats[i] == category ) {
863 returnMe = task.match( r );
864 break;
865 }
866 }
867 }
868 return returnMe;
869}
870
871static QString journalFileName()
872{
873 QString str;
874 str = getenv( "HOME" );
875 str += "/.opie_todojournal";
876 return str;
877}
878static ToDoEvent xmlToEvent( XMLElement *element )
879{
880 QString dummy;
881 ToDoEvent event;
882 bool ok;
883 int dumInt;
884 // completed
885 dummy = element->attribute("Completed" );
886 dumInt = dummy.toInt(&ok );
887 if(ok ) event.setCompleted( dumInt == 0 ? false : true );
888 // hasDate
889 dummy = element->attribute("HasDate" );
890 dumInt = dummy.toInt(&ok );
891 if(ok ) event.setHasDate( dumInt == 0 ? false: true );
892 // set the date
893 bool hasDa = dumInt;
894 if ( hasDa ) { //parse the date
895 int year, day, month = 0;
896 year = day = month;
897 // year
898 dummy = element->attribute("DateYear" );
899 dumInt = dummy.toInt(&ok );
900 if( ok ) year = dumInt;
901 // month
902 dummy = element->attribute("DateMonth" );
903 dumInt = dummy.toInt(&ok );
904 if(ok ) month = dumInt;
905 dummy = element->attribute("DateDay" );
906 dumInt = dummy.toInt(&ok );
907 if(ok ) day = dumInt;
908 // set the date
909 QDate date( year, month, day );
910 event.setDate( date);
911 }
912 dummy = element->attribute("Priority" );
913 dumInt = dummy.toInt(&ok );
914 if(!ok ) dumInt = ToDoEvent::NORMAL;
915 event.setPriority( dumInt );
916 //description
917 dummy = element->attribute("Description" );
918 event.setDescription( dummy );
919 // summary
920 dummy = element->attribute("Summary" );
921 event.setSummary( dummy );
922 // category
923 dummy = element->attribute("Categories" );
924 QStringList ids = QStringList::split(";", dummy );
925 event.setCategories( ids );
926
927 //uid
928 dummy = element->attribute("Uid" );
929 dumInt = dummy.toInt(&ok );
930 if(ok ) event.setUid( dumInt );
931 return event;
932}
933
934}
935// int TodoTable::rowHeight( int ) const
936// {
937// return 18;
938// }
939
940// int TodoTable::rowPos( int row ) const
941// {
942// return 18*row;
943// }
944
945// int TodoTable::rowAt( int pos ) const
946// {
947// return QMIN( pos/18, numRows()-1 );
948// }
949