summaryrefslogtreecommitdiff
path: root/core/pim/todo
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/pim/todo
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'core/pim/todo') (more/less context) (ignore whitespace changes)
-rw-r--r--core/pim/todo/.cvsignore4
-rw-r--r--core/pim/todo/Makefile.in201
-rw-r--r--core/pim/todo/main.cpp36
-rw-r--r--core/pim/todo/mainwindow.cpp466
-rw-r--r--core/pim/todo/mainwindow.h73
-rw-r--r--core/pim/todo/qpe-todo.control9
-rw-r--r--core/pim/todo/todo.pro19
-rw-r--r--core/pim/todo/todoentry.ui266
-rw-r--r--core/pim/todo/todoentryimpl.cpp142
-rw-r--r--core/pim/todo/todoentryimpl.h61
-rw-r--r--core/pim/todo/todotable.cpp859
-rw-r--r--core/pim/todo/todotable.h207
12 files changed, 2343 insertions, 0 deletions
diff --git a/core/pim/todo/.cvsignore b/core/pim/todo/.cvsignore
new file mode 100644
index 0000000..5ed04d8
--- a/dev/null
+++ b/core/pim/todo/.cvsignore
@@ -0,0 +1,4 @@
1moc_*
2Makefile
3todoentry.h
4todoentry.cpp
diff --git a/core/pim/todo/Makefile.in b/core/pim/todo/Makefile.in
new file mode 100644
index 0000000..f3c5f0e
--- a/dev/null
+++ b/core/pim/todo/Makefile.in
@@ -0,0 +1,201 @@
1#############################################################################
2
3####### Compiler, tools and options
4
5 CXX =$(SYSCONF_CXX) $(QT_CXX_MT)
6 CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
7 CC =$(SYSCONF_CC) $(QT_C_MT)
8 CFLAGS =$(SYSCONF_CFLAGS)
9 INCPATH =-I$(QPEDIR)/include
10 LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
11 LIBS =$(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
12 MOC =$(SYSCONF_MOC)
13 UIC =$(SYSCONF_UIC)
14
15####### Target
16
17DESTDIR = $(QPEDIR)/bin/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= todolist
22TARGET1 = lib$(TARGET).so.$(VER_MAJ)
23
24####### Files
25
26 HEADERS =mainwindow.h \
27 todotable.h \
28 todoentryimpl.h
29 SOURCES =main.cpp \
30 mainwindow.cpp \
31 todotable.cpp \
32 todoentryimpl.cpp
33 OBJECTS =main.o \
34 mainwindow.o \
35 todotable.o \
36 todoentryimpl.o \
37 todoentry.o
38INTERFACES = todoentry.ui
39UICDECLS = todoentry.h
40UICIMPLS = todoentry.cpp
41 SRCMOC =moc_mainwindow.cpp \
42 moc_todotable.cpp \
43 moc_todoentryimpl.cpp \
44 moc_todoentry.cpp
45 OBJMOC =moc_mainwindow.o \
46 moc_todotable.o \
47 moc_todoentryimpl.o \
48 moc_todoentry.o
49
50
51####### Implicit rules
52
53.SUFFIXES: .cpp .cxx .cc .C .c
54
55.cpp.o:
56 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
57
58.cxx.o:
59 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
60
61.cc.o:
62 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
63
64.C.o:
65 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
66
67.c.o:
68 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
69
70####### Build rules
71
72
73all: $(DESTDIR)$(TARGET)
74
75$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
76 $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
77
78moc: $(SRCMOC)
79
80tmake:
81 tmake todo.pro
82
83clean:
84 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
85 -rm -f *~ core
86 -rm -f allmoc.cpp
87
88####### Extension Modules
89
90listpromodules:
91 @echo
92
93listallmodules:
94 @echo
95
96listaddonpromodules:
97 @echo
98
99listaddonentmodules:
100 @echo
101
102
103REQUIRES=
104
105####### Sub-libraries
106
107
108###### Combined headers
109
110
111
112####### Compile
113
114main.o: main.cpp \
115 mainwindow.h \
116 $(QPEDIR)/include/qpe/qpeapplication.h
117
118mainwindow.o: mainwindow.cpp \
119 mainwindow.h \
120 todoentryimpl.h \
121 todoentry.h \
122 $(QPEDIR)/include/qpe/task.h \
123 $(QPEDIR)/include/qpe/palmtoprecord.h \
124 $(QPEDIR)/include/qpe/stringutil.h \
125 todotable.h \
126 $(QPEDIR)/include/qpe/categories.h \
127 $(QPEDIR)/include/qpe/qpeapplication.h \
128 $(QPEDIR)/include/qpe/config.h \
129 $(QPEDIR)/include/qpe/finddialog.h \
130 $(QPEDIR)/include/qpe/global.h \
131 $(QPEDIR)/include/qpe/ir.h \
132 $(QPEDIR)/include/qpe/qpemenubar.h \
133 $(QPEDIR)/include/qpe/qpemessagebox.h \
134 $(QPEDIR)/include/qpe/resource.h \
135 $(QPEDIR)/include/qpe/qpetoolbar.h
136
137todotable.o: todotable.cpp \
138 todotable.h \
139 $(QPEDIR)/include/qpe/categories.h \
140 $(QPEDIR)/include/qpe/task.h \
141 $(QPEDIR)/include/qpe/palmtoprecord.h \
142 $(QPEDIR)/include/qpe/stringutil.h \
143 $(QPEDIR)/include/qpe/categoryselect.h \
144 $(QPEDIR)/include/qpe/xmlreader.h
145
146todoentryimpl.o: todoentryimpl.cpp \
147 todoentryimpl.h \
148 todoentry.h \
149 $(QPEDIR)/include/qpe/task.h \
150 $(QPEDIR)/include/qpe/palmtoprecord.h \
151 $(QPEDIR)/include/qpe/stringutil.h \
152 $(QPEDIR)/include/qpe/categoryselect.h \
153 $(QPEDIR)/include/qpe/datebookmonth.h \
154 $(QPEDIR)/include/qpe/event.h \
155 $(QPEDIR)/include/qpe/global.h \
156 $(QPEDIR)/include/qpe/imageedit.h \
157 $(QPEDIR)/include/qpe/timestring.h
158
159todoentry.h: todoentry.ui
160 $(UIC) todoentry.ui -o $(INTERFACE_DECL_PATH)/todoentry.h
161
162todoentry.cpp: todoentry.ui
163 $(UIC) todoentry.ui -i todoentry.h -o todoentry.cpp
164
165todoentry.o: todoentry.cpp \
166 todoentry.h \
167 todoentry.ui
168
169moc_mainwindow.o: moc_mainwindow.cpp \
170 mainwindow.h
171
172moc_todotable.o: moc_todotable.cpp \
173 todotable.h \
174 $(QPEDIR)/include/qpe/categories.h \
175 $(QPEDIR)/include/qpe/task.h \
176 $(QPEDIR)/include/qpe/palmtoprecord.h \
177 $(QPEDIR)/include/qpe/stringutil.h
178
179moc_todoentryimpl.o: moc_todoentryimpl.cpp \
180 todoentryimpl.h \
181 todoentry.h \
182 $(QPEDIR)/include/qpe/task.h \
183 $(QPEDIR)/include/qpe/palmtoprecord.h \
184 $(QPEDIR)/include/qpe/stringutil.h
185
186moc_todoentry.o: moc_todoentry.cpp \
187 todoentry.h
188
189moc_mainwindow.cpp: mainwindow.h
190 $(MOC) mainwindow.h -o moc_mainwindow.cpp
191
192moc_todotable.cpp: todotable.h
193 $(MOC) todotable.h -o moc_todotable.cpp
194
195moc_todoentryimpl.cpp: todoentryimpl.h
196 $(MOC) todoentryimpl.h -o moc_todoentryimpl.cpp
197
198moc_todoentry.cpp: todoentry.h
199 $(MOC) todoentry.h -o moc_todoentry.cpp
200
201
diff --git a/core/pim/todo/main.cpp b/core/pim/todo/main.cpp
new file mode 100644
index 0000000..4e1c8a1
--- a/dev/null
+++ b/core/pim/todo/main.cpp
@@ -0,0 +1,36 @@
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 "mainwindow.h"
22
23#include <qpe/qpeapplication.h>
24
25int main( int argc, char **argv )
26{
27 QPEApplication a( argc, argv );
28
29 TodoWindow mw;
30 QObject::connect( &a, SIGNAL( flush() ), &mw, SLOT( flush() ) );
31 QObject::connect( &a, SIGNAL( reload() ), &mw, SLOT( reload() ) );
32
33 a.showMainWidget(&mw);
34
35 return a.exec();
36}
diff --git a/core/pim/todo/mainwindow.cpp b/core/pim/todo/mainwindow.cpp
new file mode 100644
index 0000000..fb85a09
--- a/dev/null
+++ b/core/pim/todo/mainwindow.cpp
@@ -0,0 +1,466 @@
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 "mainwindow.h"
22#include "todoentryimpl.h"
23#include "todotable.h"
24
25#include <qpe/qpeapplication.h>
26#include <qpe/config.h>
27#include <qpe/finddialog.h>
28#include <qpe/global.h>
29#include <qpe/ir.h>
30#include <qpe/qpemenubar.h>
31#include <qpe/qpemessagebox.h>
32#include <qpe/resource.h>
33#include <qpe/task.h>
34#include <qpe/qpetoolbar.h>
35
36#include <qaction.h>
37#include <qarray.h>
38#include <qdatastream.h>
39#include <qdatetime.h>
40#include <qfile.h>
41#include <qmessagebox.h>
42#include <qpopupmenu.h>
43
44#include <sys/stat.h>
45#include <sys/types.h>
46#include <fcntl.h>
47#include <unistd.h>
48
49#include <stdlib.h>
50
51static QString todolistXMLFilename()
52{
53 return Global::applicationFileName("todolist","todolist.xml");
54}
55
56static QString categoriesXMLFilename()
57{
58 return Global::applicationFileName("todolist","categories.xml");
59}
60
61TodoWindow::TodoWindow( QWidget *parent, const char *name, WFlags f = 0 ) :
62 QMainWindow( parent, name, f ), syncing(FALSE)
63{
64// QTime t;
65// t.start();
66
67 setCaption( tr("Todo") );
68 QString str;
69 table = new TodoTable( this );
70 table->setColumnWidth( 2, 10 );
71 table->setPaintingEnabled( FALSE );
72 table->setUpdatesEnabled( FALSE );
73 table->viewport()->setUpdatesEnabled( FALSE );
74
75 {
76 str = todolistXMLFilename();
77 if ( str.isNull() )
78 QMessageBox::critical( this,
79 tr("Out of Space"),
80 tr("Unable to create startup files\n"
81 "Free up some space\n"
82 "before you enter any data") );
83 else
84 table->load( str );
85 }
86
87 // repeat for categories...
88 str = categoriesXMLFilename();
89 if ( str.isNull() )
90 QMessageBox::critical( this,
91 tr( "Out of Space" ),
92 tr( "Unable to create startup files\n"
93 "Free up some space\n"
94 "before you enter any data") );
95
96 setCentralWidget( table );
97 setToolBarsMovable( FALSE );
98
99// qDebug("after load: t=%d", t.elapsed() );
100
101 Config config( "todo" );
102 config.setGroup( "View" );
103 bool complete = config.readBoolEntry( "ShowComplete", true );
104 table->setShowCompleted( complete );
105 QString category = config.readEntry( "Category", QString::null );
106 table->setShowCategory( category );
107
108 QPEToolBar *bar = new QPEToolBar( this );
109 bar->setHorizontalStretchable( TRUE );
110
111 QPEMenuBar *mb = new QPEMenuBar( bar );
112
113 catMenu = new QPopupMenu( this );
114 QPopupMenu *edit = new QPopupMenu( this );
115 contextMenu = new QPopupMenu( this );
116
117 bar = new QPEToolBar( this );
118
119 QAction *a = new QAction( tr( "New Task" ), Resource::loadPixmap( "new" ),
120 QString::null, 0, this, 0 );
121 connect( a, SIGNAL( activated() ),
122 this, SLOT( slotNew() ) );
123 a->addTo( bar );
124 a->addTo( edit );
125 a = new QAction( tr( "Edit" ), Resource::loadIconSet( "edit" ),
126 QString::null, 0, this, 0 );
127 connect( a, SIGNAL( activated() ),
128 this, SLOT( slotEdit() ) );
129 a->addTo( bar );
130 a->addTo( edit );
131 a->addTo( contextMenu );
132 a->setEnabled( FALSE );
133 editAction = a;
134 a = new QAction( tr( "Delete" ), Resource::loadIconSet( "trash" ),
135 QString::null, 0, this, 0 );
136 connect( a, SIGNAL( activated() ),
137 this, SLOT( slotDelete() ) );
138 a->addTo( bar );
139 a->addTo( edit );
140 a->addTo( contextMenu );
141 a->setEnabled( FALSE );
142 deleteAction = a;
143
144 if ( Ir::supported() ) {
145 a = new QAction( tr( "Beam" ), Resource::loadPixmap( "beam" ),
146 QString::null, 0, this, 0 );
147 connect( a, SIGNAL( activated() ),
148 this, SLOT( slotBeam() ) );
149 a->addTo( edit );
150 a->addTo( bar );
151 }
152
153 a = new QAction( tr( "Find" ), Resource::loadIconSet( "mag" ),
154 QString::null, 0, this, 0 );
155 connect( a, SIGNAL( activated() ),
156 this, SLOT( slotFind() ) );
157 a->addTo( bar );
158 a->addTo( edit );
159 if ( table->numRows() )
160 a->setEnabled( TRUE );
161 else
162 a->setEnabled( FALSE );
163
164 //a->setEnabled( FALSE );
165 findAction = a;
166// qDebug("mainwindow #2: t=%d", t.elapsed() );
167
168 completedAction = new QAction( QString::null, tr("Completed tasks"), 0, this, 0, TRUE );
169
170 catMenu->setCheckable( true );
171 populateCategories();
172
173 mb->insertItem( tr( "Task" ), edit );
174 mb->insertItem( tr( "View" ), catMenu );
175
176 resize( 200, 300 );
177 if ( table->numRows() > 0 )
178 currentEntryChanged( 0, 0 );
179 connect( table, SIGNAL( signalEdit() ),
180 this, SLOT( slotEdit() ) );
181 connect( table, SIGNAL(signalShowMenu(const QPoint &)),
182 this, SLOT( slotShowPopup(const QPoint &)) );
183
184// qDebug("mainwindow #3: t=%d", t.elapsed() );
185 table->updateVisible();
186 table->setUpdatesEnabled( TRUE );
187 table->setPaintingEnabled( TRUE );
188 table->viewport()->setUpdatesEnabled( TRUE );
189
190 connect( completedAction, SIGNAL( toggled(bool) ), this, SLOT( showCompleted(bool) ) );
191 connect( catMenu, SIGNAL(activated(int)), this, SLOT(setCategory(int)) );
192 connect( table, SIGNAL( currentChanged( int, int ) ),
193 this, SLOT( currentEntryChanged( int, int ) ) );
194
195// qDebug("done: t=%d", t.elapsed() );
196}
197
198void TodoWindow::slotNew()
199{
200 if(syncing) {
201 QMessageBox::warning(this, tr("Todo"),
202 tr("Can not edit data, currently syncing"));
203 return;
204 }
205
206 int id;
207 id = -1;
208 QArray<int> ids;
209 ids = table->currentEntry().categories();
210 if ( ids.count() )
211 id = ids[0];
212 NewTaskDialog e( id, this, 0, TRUE );
213
214 Task todo;
215
216#if defined(Q_WS_QWS) || defined(_WS_QWS_)
217 e.showMaximized();
218#endif
219 int ret = e.exec();
220
221 if ( ret == QDialog::Accepted ) {
222 table->setPaintingEnabled( false );
223 todo = e.todoEntry();
224 todo.assignUid();
225 table->addEntry( todo );
226 table->setPaintingEnabled( true );
227 findAction->setEnabled( TRUE );
228 }
229 // I'm afraid we must call this every time now, otherwise
230 // spend expensive time comparing all these strings...
231 populateCategories();
232}
233
234TodoWindow::~TodoWindow()
235{
236}
237
238void TodoWindow::slotDelete()
239{
240 if(syncing) {
241 QMessageBox::warning(this, tr("Todo"),
242 tr("Can not edit data, currently syncing"));
243 return;
244 }
245
246 if ( table->currentRow() == -1 )
247 return;
248
249 QString strName = table->text( table->currentRow(), 2 ).left( 30 );
250
251 if ( !QPEMessageBox::confirmDelete( this, tr( "Todo" ), strName ) )
252 return;
253
254
255
256 table->setPaintingEnabled( false );
257 table->removeCurrentEntry();
258 table->setPaintingEnabled( true );
259
260 if ( table->numRows() == 0 ) {
261 currentEntryChanged( -1, 0 );
262 findAction->setEnabled( FALSE );
263 }
264}
265
266void TodoWindow::slotEdit()
267{
268 if(syncing) {
269 QMessageBox::warning(this, tr("Todo"),
270 tr("Can not edit data, currently syncing"));
271 return;
272 }
273
274 Task todo = table->currentEntry();
275
276 NewTaskDialog e( todo, this, 0, TRUE );
277 e.setCaption( tr( "Edit Task" ) );
278
279#if defined(Q_WS_QWS) || defined(_WS_QWS_)
280 e.showMaximized();
281#endif
282 int ret = e.exec();
283
284 if ( ret == QDialog::Accepted ) {
285 table->setPaintingEnabled( false );
286 todo = e.todoEntry();
287 table->replaceCurrentEntry( todo );
288 table->setPaintingEnabled( true );
289 }
290 populateCategories();
291
292}
293
294void TodoWindow::slotShowPopup( const QPoint &p )
295{
296 contextMenu->popup( p );
297}
298
299void TodoWindow::showCompleted( bool s )
300{
301 if ( !table->isUpdatesEnabled() )
302 return;
303 table->setPaintingEnabled( false );
304 table->setShowCompleted( s );
305 table->setPaintingEnabled( true );
306}
307
308void TodoWindow::currentEntryChanged( int r, int )
309{
310 if ( r != -1 && table->rowHeight( r ) > 0 ) {
311 editAction->setEnabled( TRUE );
312 deleteAction->setEnabled( TRUE );
313 } else {
314 editAction->setEnabled( FALSE );
315 deleteAction->setEnabled( FALSE );
316 }
317}
318
319void TodoWindow::setCategory( int c )
320{
321 if ( c <= 0 ) return;
322 if ( !table->isUpdatesEnabled() )
323 return;
324 table->setPaintingEnabled( false );
325 for ( unsigned int i = 1; i < catMenu->count(); i++ )
326 catMenu->setItemChecked( i, c == (int)i );
327 if ( c == 1 ) {
328 table->setShowCategory( QString::null );
329 setCaption( tr("Todo") + " - " + tr( "All" ) );
330 } else if ( c == (int)catMenu->count() - 1 ) {
331 table->setShowCategory( tr( "Unfiled" ) );
332 setCaption( tr("Todo") + " - " + tr( "Unfiled" ) );
333 } else {
334 QString cat = table->categories()[c - 2];
335 table->setShowCategory( cat );
336 setCaption( tr("Todo") + " - " + cat );
337 }
338 table->setPaintingEnabled( true );
339}
340
341void TodoWindow::populateCategories()
342{
343 catMenu->clear();
344
345 completedAction->addTo( catMenu );
346 completedAction->setOn( table->showCompleted() );
347
348 int id,
349 rememberId;
350 id = 1;
351 catMenu->insertItem( tr( "All" ), id++ );
352// catMenu->insertSeparator();
353 QStringList categories = table->categories();
354 categories.append( tr( "Unfiled" ) );
355 for ( QStringList::Iterator it = categories.begin();
356 it != categories.end(); ++it ) {
357 catMenu->insertItem( *it, id );
358 if ( *it == table->showCategory() )
359 rememberId = id;
360 ++id;
361 }
362 if ( table->showCategory().isEmpty() )
363 setCategory( 1 );
364 else
365 setCategory( rememberId );
366}
367
368void TodoWindow::reload()
369{
370 table->clear();
371 table->load( todolistXMLFilename() );
372 syncing = FALSE;
373}
374
375void TodoWindow::flush()
376{
377 syncing = TRUE;
378 table->save( todolistXMLFilename() );
379}
380
381void TodoWindow::closeEvent( QCloseEvent *e )
382{
383 if(syncing) {
384 /* no need to save if in the middle of syncing */
385 e->accept();
386 return;
387 }
388
389 if ( table->save( todolistXMLFilename() ) ) {
390 e->accept();
391 // repeat for categories...
392 // if writing configs fail, it will emit an
393 // error, but I feel that it is "ok" for us to exit
394 // espically since we aren't told if the write succeeded...
395 Config config( "todo" );
396 config.setGroup( "View" );
397 config.writeEntry( "ShowComplete", table->showCompleted() );
398 config.writeEntry( "Category", table->showCategory() );
399 } else {
400 if ( QMessageBox::critical( this, tr("Out of space"),
401 tr("Todo was unable\n"
402 "to save your changes.\n"
403 "Free up some space\n"
404 "and try again.\n"
405 "\nQuit Anyway?"),
406 QMessageBox::Yes|QMessageBox::Escape,
407 QMessageBox::No|QMessageBox::Default)
408 != QMessageBox::No )
409 e->accept();
410 else
411 e->ignore();
412 }
413}
414
415void TodoWindow::slotFind()
416{
417 // put everything back to view all for searching...
418 if ( !catMenu->isItemChecked( 0 ) )
419 setCategory( 0 );
420
421 FindDialog dlg( "Todo List", this );
422 QObject::connect( &dlg,
423 SIGNAL(signalFindClicked(const QString &,
424 bool, bool, int)),
425 table,
426 SLOT(slotDoFind(const QString&, bool, bool, int)) );
427 QObject::connect( table, SIGNAL(signalNotFound()), &dlg,
428 SLOT(slotNotFound()) );
429 QObject::connect( table, SIGNAL(signalWrapAround()), &dlg,
430 SLOT(slotWrapAround()) );
431 dlg.exec();
432 if ( table->numSelections() )
433 table->clearSelection();
434 table->clearFindRow();
435}
436
437
438void TodoWindow::setDocument( const QString &filename )
439{
440 if ( filename.find(".vcs") != int(filename.length()) - 4 ) return;
441
442 QValueList<Task> tl = Task::readVCalendar( filename );
443 for( QValueList<Task>::Iterator it = tl.begin(); it != tl.end(); ++it ) {
444 table->addEntry( *it );
445 }
446}
447
448static const char * beamfile = "/tmp/obex/todo.vcs";
449
450void TodoWindow::slotBeam()
451{
452 unlink( beamfile ); // delete if exists
453 Task c = table->currentEntry();
454 mkdir("/tmp/obex/", 0755);
455 Task::writeVCalendar( beamfile, c );
456 Ir *ir = new Ir( this );
457 connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) );
458 QString description = c.description();
459 ir->send( beamfile, description, "text/x-vCalendar" );
460}
461
462void TodoWindow::beamDone( Ir *ir )
463{
464 delete ir;
465 unlink( beamfile );
466}
diff --git a/core/pim/todo/mainwindow.h b/core/pim/todo/mainwindow.h
new file mode 100644
index 0000000..f4fcd1b
--- a/dev/null
+++ b/core/pim/todo/mainwindow.h
@@ -0,0 +1,73 @@
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#ifndef MAINWINDOW_H
22#define MAINWINDOW_H
23
24#include <qmainwindow.h>
25
26class TodoTable;
27class QAction;
28class QPopupMenu;
29class Ir;
30
31class TodoWindow : public QMainWindow
32{
33 Q_OBJECT
34
35public:
36 TodoWindow( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
37 ~TodoWindow();
38
39public slots:
40 void flush();
41 void reload();
42
43protected slots:
44 void slotNew();
45 void slotDelete();
46 void slotEdit();
47 void slotShowPopup( const QPoint & );
48 void showCompleted( bool );
49 void currentEntryChanged( int r, int c );
50 void setCategory( int );
51 void slotFind();
52 void setDocument( const QString & );
53 void slotBeam();
54 void beamDone( Ir * );
55
56protected:
57 void closeEvent( QCloseEvent *e );
58
59private:
60 void populateCategories();
61
62private:
63 TodoTable *table;
64 QAction *editAction,
65 *deleteAction,
66 *findAction,
67 * completedAction;
68 QPopupMenu *contextMenu, *catMenu;
69
70 bool syncing;
71};
72
73#endif
diff --git a/core/pim/todo/qpe-todo.control b/core/pim/todo/qpe-todo.control
new file mode 100644
index 0000000..80195a0
--- a/dev/null
+++ b/core/pim/todo/qpe-todo.control
@@ -0,0 +1,9 @@
1Files: bin/todolist apps/Applications/todo.desktop
2Priority: optional
3Section: qpe/applications
4Maintainer: Warwick Allison <warwick@trolltech.com>
5Architecture: arm
6Version: $QPE_VERSION-3
7Depends: qpe-base ($QPE_VERSION)
8Description: TODO-list manager
9 A Todo-list manager for the Qtopia environment.
diff --git a/core/pim/todo/todo.pro b/core/pim/todo/todo.pro
new file mode 100644
index 0000000..e28ea1c
--- a/dev/null
+++ b/core/pim/todo/todo.pro
@@ -0,0 +1,19 @@
1 TEMPLATE= app
2 CONFIG = qt warn_on release
3 DESTDIR = $(QPEDIR)/bin
4 HEADERS= mainwindow.h \
5 todotable.h \
6 todoentryimpl.h
7 SOURCES= main.cpp \
8 mainwindow.cpp \
9 todotable.cpp \
10 todoentryimpl.cpp
11
12 INTERFACES= todoentry.ui
13
14 TARGET = todolist
15INCLUDEPATH += $(QPEDIR)/include
16 DEPENDPATH+= $(QPEDIR)/include
17LIBS += -lqpe
18
19TRANSLATIONS = ../i18n/de/todolist.ts
diff --git a/core/pim/todo/todoentry.ui b/core/pim/todo/todoentry.ui
new file mode 100644
index 0000000..c735e76
--- a/dev/null
+++ b/core/pim/todo/todoentry.ui
@@ -0,0 +1,266 @@
1<!DOCTYPE UI><UI>
2<class>NewTaskDialogBase</class>
3<comment>*********************************************************************
4** Copyright (C) 2000 Trolltech AS. All rights reserved.
5**
6** This file is part of Qtopia Environment.
7**
8** This file may be distributed and/or modified under the terms of the
9** GNU General Public License version 2 as published by the Free Software
10** Foundation and appearing in the file LICENSE.GPL included in the
11** packaging of this file.
12**
13** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
14** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15**
16** See http://www.trolltech.com/gpl/ for GPL licensing information.
17**
18** Contact info@trolltech.com if any conditions of this licensing are
19** not clear to you.
20**
21*********************************************************************</comment>
22<widget>
23 <class>QDialog</class>
24 <property stdset="1">
25 <name>name</name>
26 <cstring>NewTaskDialogBase</cstring>
27 </property>
28 <property stdset="1">
29 <name>geometry</name>
30 <rect>
31 <x>0</x>
32 <y>0</y>
33 <width>249</width>
34 <height>321</height>
35 </rect>
36 </property>
37 <property stdset="1">
38 <name>caption</name>
39 <string>New Task</string>
40 </property>
41 <property>
42 <name>layoutMargin</name>
43 </property>
44 <property>
45 <name>layoutSpacing</name>
46 </property>
47 <vbox>
48 <property stdset="1">
49 <name>margin</name>
50 <number>0</number>
51 </property>
52 <property stdset="1">
53 <name>spacing</name>
54 <number>0</number>
55 </property>
56 <widget>
57 <class>QLayoutWidget</class>
58 <property stdset="1">
59 <name>name</name>
60 <cstring>Layout4</cstring>
61 </property>
62 <hbox>
63 <property stdset="1">
64 <name>margin</name>
65 <number>0</number>
66 </property>
67 <property stdset="1">
68 <name>spacing</name>
69 <number>6</number>
70 </property>
71 <widget>
72 <class>QLabel</class>
73 <property stdset="1">
74 <name>name</name>
75 <cstring>TextLabel2</cstring>
76 </property>
77 <property stdset="1">
78 <name>text</name>
79 <string>Priority:</string>
80 </property>
81 </widget>
82 <widget>
83 <class>QComboBox</class>
84 <item>
85 <property>
86 <name>text</name>
87 <string>1 - Very High</string>
88 </property>
89 </item>
90 <item>
91 <property>
92 <name>text</name>
93 <string>2 - High</string>
94 </property>
95 </item>
96 <item>
97 <property>
98 <name>text</name>
99 <string>3 - Normal</string>
100 </property>
101 </item>
102 <item>
103 <property>
104 <name>text</name>
105 <string>4 - Low</string>
106 </property>
107 </item>
108 <item>
109 <property>
110 <name>text</name>
111 <string>5 - Very Low</string>
112 </property>
113 </item>
114 <property stdset="1">
115 <name>name</name>
116 <cstring>comboPriority</cstring>
117 </property>
118 <property stdset="1">
119 <name>sizePolicy</name>
120 <sizepolicy>
121 <hsizetype>7</hsizetype>
122 <vsizetype>0</vsizetype>
123 </sizepolicy>
124 </property>
125 <property stdset="1">
126 <name>currentItem</name>
127 <number>2</number>
128 </property>
129 </widget>
130 </hbox>
131 </widget>
132 <widget>
133 <class>QLayoutWidget</class>
134 <property stdset="1">
135 <name>name</name>
136 <cstring>Layout3</cstring>
137 </property>
138 <hbox>
139 <property stdset="1">
140 <name>margin</name>
141 <number>0</number>
142 </property>
143 <property stdset="1">
144 <name>spacing</name>
145 <number>6</number>
146 </property>
147 <widget>
148 <class>QLabel</class>
149 <property stdset="1">
150 <name>name</name>
151 <cstring>TextLabel3</cstring>
152 </property>
153 <property stdset="1">
154 <name>frameShape</name>
155 <enum>NoFrame</enum>
156 </property>
157 <property stdset="1">
158 <name>text</name>
159 <string>Category:</string>
160 </property>
161 </widget>
162 <widget>
163 <class>CategorySelect</class>
164 <property stdset="1">
165 <name>name</name>
166 <cstring>comboCategory</cstring>
167 </property>
168 </widget>
169 </hbox>
170 </widget>
171 <widget>
172 <class>QLayoutWidget</class>
173 <property stdset="1">
174 <name>name</name>
175 <cstring>Layout4</cstring>
176 </property>
177 <hbox>
178 <property stdset="1">
179 <name>margin</name>
180 <number>0</number>
181 </property>
182 <property stdset="1">
183 <name>spacing</name>
184 <number>6</number>
185 </property>
186 <widget>
187 <class>QCheckBox</class>
188 <property stdset="1">
189 <name>name</name>
190 <cstring>checkCompleted</cstring>
191 </property>
192 <property stdset="1">
193 <name>text</name>
194 <string>&amp;Completed</string>
195 </property>
196 </widget>
197 <widget>
198 <class>QCheckBox</class>
199 <property stdset="1">
200 <name>name</name>
201 <cstring>checkDate</cstring>
202 </property>
203 <property stdset="1">
204 <name>text</name>
205 <string>D&amp;ue</string>
206 </property>
207 </widget>
208 <widget>
209 <class>QPushButton</class>
210 <property stdset="1">
211 <name>name</name>
212 <cstring>buttonDate</cstring>
213 </property>
214 <property stdset="1">
215 <name>enabled</name>
216 <bool>false</bool>
217 </property>
218 <property stdset="1">
219 <name>text</name>
220 <string>1 Jan 2001</string>
221 </property>
222 </widget>
223 </hbox>
224 </widget>
225 <widget>
226 <class>QMultiLineEdit</class>
227 <property stdset="1">
228 <name>name</name>
229 <cstring>txtTodo</cstring>
230 </property>
231 </widget>
232 </vbox>
233</widget>
234<customwidgets>
235 <customwidget>
236 <class>CategorySelect</class>
237 <header location="global">qpe/categoryselect.h</header>
238 <sizehint>
239 <width>-1</width>
240 <height>-1</height>
241 </sizehint>
242 <container>0</container>
243 <sizepolicy>
244 <hordata>7</hordata>
245 <verdata>1</verdata>
246 </sizepolicy>
247 <pixmap>image0</pixmap>
248 </customwidget>
249</customwidgets>
250<images>
251 <image>
252 <name>image0</name>
253 <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
254 </image>
255</images>
256<connections>
257 <connection>
258 <sender>checkDate</sender>
259 <signal>toggled(bool)</signal>
260 <receiver>buttonDate</receiver>
261 <slot>setEnabled(bool)</slot>
262 </connection>
263 <slot access="protected">dateChanged( const QString &amp; )</slot>
264 <slot access="protected">dateChanged( int, int, int )</slot>
265</connections>
266</UI>
diff --git a/core/pim/todo/todoentryimpl.cpp b/core/pim/todo/todoentryimpl.cpp
new file mode 100644
index 0000000..79206de
--- a/dev/null
+++ b/core/pim/todo/todoentryimpl.cpp
@@ -0,0 +1,142 @@
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 "todoentryimpl.h"
22
23#include <qpe/categoryselect.h>
24#include <qpe/datebookmonth.h>
25#include <qpe/global.h>
26#include <qpe/imageedit.h>
27#include <qpe/task.h>
28#include <qpe/timestring.h>
29
30#include <qmessagebox.h>
31#include <qpopupmenu.h>
32#include <qtoolbutton.h>
33#include <qcombobox.h>
34#include <qcheckbox.h>
35#include <qlineedit.h>
36#include <qmultilineedit.h>
37#include <qlabel.h>
38#include <qtimer.h>
39#include <qapplication.h>
40
41
42NewTaskDialog::NewTaskDialog( const Task& task, QWidget *parent,
43 const char *name, bool modal, WFlags fl )
44 : NewTaskDialogBase( parent, name, modal, fl ),
45 todo( task )
46{
47 todo.setCategories( task.categories() );
48 if ( todo.hasDueDate() )
49 date = todo.dueDate();
50 else
51 date = QDate::currentDate();
52
53 init();
54 comboPriority->setCurrentItem( task.priority() - 1 );
55
56 checkCompleted->setChecked( task.isCompleted() );
57 checkDate->setChecked( task.hasDueDate() );
58 buttonDate->setText( TimeString::longDateString( date ) );
59
60 txtTodo->setText( task.description() );
61}
62
63/*
64 * Constructs a NewTaskDialog which is a child of 'parent', with the
65 * name 'name' and widget flags set to 'f'
66 *
67 * The dialog will by default be modeless, unless you set 'modal' to
68 * TRUE to construct a modal dialog.
69 */
70NewTaskDialog::NewTaskDialog( int id, QWidget* parent, const char* name, bool modal,
71 WFlags fl )
72 : NewTaskDialogBase( parent, name, modal, fl ),
73 date( QDate::currentDate() )
74{
75 if ( id != -1 ) {
76 QArray<int> ids( 1 );
77 ids[0] = id;
78 todo.setCategories( ids );
79 }
80 init();
81}
82
83void NewTaskDialog::init()
84{
85 QPopupMenu *m1 = new QPopupMenu( this );
86 picker = new DateBookMonth( m1, 0, TRUE );
87 m1->insertItem( picker );
88 buttonDate->setPopup( m1 );
89 comboCategory->setCategories( todo.categories(), "Todo List", tr("Todo List") );
90
91 connect( picker, SIGNAL( dateClicked( int, int, int ) ),
92 this, SLOT( dateChanged( int, int, int ) ) );
93
94 buttonDate->setText( TimeString::longDateString( date ) );
95 picker->setDate( date.year(), date.month(), date.day() );
96}
97
98/*
99 * Destroys the object and frees any allocated resources
100 */
101NewTaskDialog::~NewTaskDialog()
102{
103 // no need to delete child widgets, Qt does it all for us
104}
105void NewTaskDialog::dateChanged( int y, int m, int d )
106{
107 date = QDate( y, m, d );
108 buttonDate->setText( TimeString::longDateString( date ) );
109}
110
111/*!
112*/
113
114Task NewTaskDialog::todoEntry()
115{
116 todo.setDueDate( date, checkDate->isChecked() );
117 if ( comboCategory->currentCategory() != -1 ) {
118 todo.setCategories( comboCategory->currentCategories() );
119 }
120 todo.setPriority( comboPriority->currentItem() + 1 );
121 todo.setCompleted( checkCompleted->isChecked() );
122
123 todo.setDescription( txtTodo->text() );
124
125 return todo;
126}
127
128
129/*!
130
131*/
132
133void NewTaskDialog::accept()
134{
135 QString strText = txtTodo->text();
136 if ( !strText || strText == "") {
137 // hmm... just decline it then, the user obviously didn't care about it
138 QDialog::reject();
139 return;
140 }
141 QDialog::accept();
142}
diff --git a/core/pim/todo/todoentryimpl.h b/core/pim/todo/todoentryimpl.h
new file mode 100644
index 0000000..932d66e
--- a/dev/null
+++ b/core/pim/todo/todoentryimpl.h
@@ -0,0 +1,61 @@
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#ifndef NEWTASKDIALOG_H
22#define NEWTASKDIALOG_H
23
24#include "todoentry.h"
25
26#include <qpe/task.h>
27
28#include <qdatetime.h>
29#include <qpalette.h>
30
31class QLabel;
32class QTimer;
33class DateBookMonth;
34
35class NewTaskDialog : public NewTaskDialogBase
36{
37 Q_OBJECT
38
39public:
40 NewTaskDialog( const Task &task, QWidget *parent = 0, const char* name = 0,
41 bool modal = FALSE, WFlags fl = 0 );
42 NewTaskDialog( int id, QWidget* parent = 0, const char* name = 0,
43 bool modal = FALSE, WFlags fl = 0 );
44 ~NewTaskDialog();
45
46 Task todoEntry();
47
48protected slots:
49 void dateChanged( int y, int m, int d );
50
51protected:
52 virtual void accept();
53
54private:
55 void init();
56 Task todo;
57 QDate date;
58 DateBookMonth *picker;
59};
60
61#endif // NEWTASKDIALOG_H
diff --git a/core/pim/todo/todotable.cpp b/core/pim/todo/todotable.cpp
new file mode 100644
index 0000000..77d3389
--- a/dev/null
+++ b/core/pim/todo/todotable.cpp
@@ -0,0 +1,859 @@
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 "todotable.h"
22
23#include <qpe/categoryselect.h>
24#include <qpe/xmlreader.h>
25
26#include <qasciidict.h>
27#include <qcombobox.h>
28#include <qfile.h>
29#include <qpainter.h>
30#include <qtextcodec.h>
31#include <qtimer.h>
32#include <qdatetime.h>
33
34#include <qcursor.h>
35#include <qregexp.h>
36
37#include <errno.h>
38#include <stdlib.h>
39
40
41
42static bool taskCompare( const Task &task, const QRegExp &r, int category );
43
44static QString journalFileName();
45
46CheckItem::CheckItem( QTable *t, const QString &key )
47 : QTableItem( t, Never, "" ), checked( FALSE ), sortKey( key )
48{
49}
50
51QString CheckItem::key() const
52{
53 return sortKey;
54}
55
56void CheckItem::setChecked( bool b )
57{
58 checked = b;
59 table()->updateCell( row(), col() );
60}
61
62void CheckItem::toggle()
63{
64 TodoTable *parent = static_cast<TodoTable*>(table());
65 Task newTodo = parent->currentEntry();
66 checked = !checked;
67 newTodo.setCompleted( checked );
68 table()->updateCell( row(), col() );
69 parent->replaceCurrentEntry( newTodo, true );
70}
71
72bool CheckItem::isChecked() const
73{
74 return checked;
75}
76
77static const int BoxSize = 10;
78
79void CheckItem::paint( QPainter *p, const QColorGroup &cg, const QRect &cr,
80 bool )
81{
82 p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) );
83
84 int marg = ( cr.width() - BoxSize ) / 2;
85 int x = 0;
86 int y = ( cr.height() - BoxSize ) / 2;
87 p->setPen( QPen( cg.text() ) );
88 p->drawRect( x + marg, y, BoxSize, BoxSize );
89 p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 );
90 p->setPen( darkGreen );
91 x += 1;
92 y += 1;
93 if ( checked ) {
94 QPointArray a( 7*2 );
95 int i, xx, yy;
96 xx = x+1+marg;
97 yy = y+2;
98 for ( i=0; i<3; i++ ) {
99 a.setPoint( 2*i, xx, yy );
100 a.setPoint( 2*i+1, xx, yy+2 );
101 xx++; yy++;
102 }
103 yy -= 2;
104 for ( i=3; i<7; i++ ) {
105 a.setPoint( 2*i, xx, yy );
106 a.setPoint( 2*i+1, xx, yy+2 );
107 xx++; yy--;
108 }
109 p->drawLineSegments( a );
110 }
111}
112
113
114ComboItem::ComboItem( QTable *t, EditType et )
115 : QTableItem( t, et, "3" ), cb( 0 )
116{
117 setReplaceable( FALSE );
118}
119
120QWidget *ComboItem::createEditor() const
121{
122 QString txt = text();
123 ( (ComboItem*)this )->cb = new QComboBox( table()->viewport() );
124 cb->insertItem( "1" );
125 cb->insertItem( "2" );
126 cb->insertItem( "3" );
127 cb->insertItem( "4" );
128 cb->insertItem( "5" );
129 cb->setCurrentItem( txt.toInt() - 1 );
130 return cb;
131}
132
133void ComboItem::setContentFromEditor( QWidget *w )
134{
135 TodoTable *parent = static_cast<TodoTable*>(table());
136 Task newTodo = parent->currentEntry();
137
138 if ( w->inherits( "QComboBox" ) )
139 setText( ( (QComboBox*)w )->currentText() );
140 else
141 QTableItem::setContentFromEditor( w );
142 newTodo.setPriority( text().toInt() );
143 parent->replaceCurrentEntry( newTodo, true );
144}
145
146void ComboItem::setText( const QString &s )
147{
148 if ( cb )
149 cb->setCurrentItem( s.toInt() - 1 );
150 QTableItem::setText( s );
151}
152
153QString ComboItem::text() const
154{
155 if ( cb )
156 return cb->currentText();
157 return QTableItem::text();
158}
159
160
161
162TodoTable::TodoTable( QWidget *parent, const char *name )
163// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR
164// : QTable( 0, 3, parent, name, TRUE ),
165// #else
166 : QTable( 0, 3, parent, name ),
167// #endif
168 showComp( true ),
169 enablePainting( true ),
170 mCat( 0 ),
171 currFindRow( -2 )
172{
173 mCat.load( categoryFileName() );
174 setSorting( TRUE );
175 setSelectionMode( NoSelection );
176 setColumnStretchable( 2, TRUE );
177 setColumnWidth( 0, 20 );
178 setColumnWidth( 1, 35 );
179 setLeftMargin( 0 );
180 verticalHeader()->hide();
181 horizontalHeader()->setLabel( 0, tr( "C." ) );
182 horizontalHeader()->setLabel( 1, tr( "Prior." ) );
183 horizontalHeader()->setLabel( 2, tr( "Description" ) );
184 connect( this, SIGNAL( clicked( int, int, int, const QPoint & ) ),
185 this, SLOT( slotClicked( int, int, int, const QPoint & ) ) );
186 connect( this, SIGNAL( pressed( int, int, int, const QPoint & ) ),
187 this, SLOT( slotPressed( int, int, int, const QPoint & ) ) );
188 connect( this, SIGNAL( valueChanged( int, int ) ),
189 this, SLOT( slotCheckPriority( int, int ) ) );
190 connect( this, SIGNAL( currentChanged( int, int ) ),
191 this, SLOT( slotCurrentChanged( int, int ) ) );
192
193 menuTimer = new QTimer( this );
194 connect( menuTimer, SIGNAL(timeout()), this, SLOT(slotShowMenu()) );
195}
196
197void TodoTable::addEntry( const Task &todo )
198{
199 int row = numRows();
200 setNumRows( row + 1 );
201 updateJournal( todo, ACTION_ADD );
202 insertIntoTable( new Task(todo), row );
203 setCurrentCell(row, currentColumn());
204 updateVisible();
205}
206
207void TodoTable::slotClicked( int row, int col, int, const QPoint &pos )
208{
209 if ( !cellGeometry( row, col ).contains(pos) )
210 return;
211 // let's switch on the column number...
212 switch ( col )
213 {
214 case 0: {
215 CheckItem *i = static_cast<CheckItem*>(item( row, col ));
216 if ( i ) {
217 int x = pos.x() - columnPos( col );
218 int y = pos.y() - rowPos( row );
219 int w = columnWidth( col );
220 int h = rowHeight( row );
221 if ( i && x >= ( w - BoxSize ) / 2 && x <= ( w - BoxSize ) / 2 + BoxSize &&
222 y >= ( h - BoxSize ) / 2 && y <= ( h - BoxSize ) / 2 + BoxSize ) {
223 i->toggle();
224 }
225 emit signalDoneChanged( i->isChecked() );
226 }
227 }
228 break;
229 case 1:
230 break;
231 case 2:
232 // may as well edit it...
233 menuTimer->stop();
234// emit signalEdit();
235 break;
236 }
237}
238
239void TodoTable::slotPressed( int row, int col, int, const QPoint &pos )
240{
241 if ( col == 2 && cellGeometry( row, col ).contains(pos) )
242 menuTimer->start( 750, TRUE );
243}
244
245void TodoTable::slotShowMenu()
246{
247 emit signalShowMenu( QCursor::pos() );
248}
249
250void TodoTable::slotCurrentChanged( int, int )
251{
252 menuTimer->stop();
253}
254
255void TodoTable::internalAddEntries( QList<Task> &list )
256{
257 setNumRows( list.count() );
258 int row = 0;
259 Task *it;
260 for ( it = list.first(); it; it = list.next() )
261 insertIntoTable( it, row++ );
262}
263
264
265Task TodoTable::currentEntry() const
266{
267 QTableItem *i = item( currentRow(), 0 );
268 if ( !i || rowHeight( currentRow() ) <= 0 )
269 return Task();
270 Task *todo = todoList[(CheckItem*)i];
271 todo->setCompleted( ( (CheckItem*)item( currentRow(), 0 ) )->isChecked() );
272 todo->setPriority( ( (ComboItem*)item( currentRow(), 1 ) )->text().toInt() );
273 return *todo;
274}
275
276void TodoTable::replaceCurrentEntry( const Task &todo, bool fromTableItem )
277{
278 int row = currentRow();
279 updateJournal( todo, ACTION_REPLACE, row );
280
281 if ( !fromTableItem ) {
282 journalFreeReplaceEntry( todo, row );
283 updateVisible();
284 }
285}
286
287void TodoTable::removeCurrentEntry()
288{
289 Task *oldTodo;
290 int row = currentRow();
291 CheckItem *chk;
292
293 chk = static_cast<CheckItem*>(item(row, 0 ));
294 if ( !chk )
295 return;
296 oldTodo = todoList[chk];
297 todoList.remove( chk );
298 oldTodo->setCompleted( chk->isChecked() );
299 oldTodo->setPriority( static_cast<ComboItem*>(item(row, 1))->text().toInt() );
300 realignTable( row );
301 updateVisible();
302 updateJournal( *oldTodo, ACTION_REMOVE, row );
303 delete oldTodo;
304}
305
306
307bool TodoTable::save( const QString &fn )
308{
309 QString strNewFile = fn + ".new";
310 QFile f( strNewFile );
311 if ( !f.open( IO_WriteOnly|IO_Raw ) )
312 return false;
313
314 QString buf("<!DOCTYPE Tasks>\n<Tasks>\n");
315 QCString str;
316 int total_written;
317
318 for ( QMap<CheckItem*, Task *>::Iterator it = todoList.begin();
319 it != todoList.end(); ++it ) {
320 if ( !item( it.key()->row(), 0 ) )
321 continue;
322 Task *todo = *it;
323 // sync item with table
324 todo->setCompleted( ((CheckItem*)item(it.key()->row(), 0))->isChecked() );
325 todo->setPriority( ((ComboItem*)item( it.key()->row(), 1))->text().toInt() );
326 buf += "<Task";
327 todo->save( buf );
328 buf += " />\n";
329 str = buf.utf8();
330 total_written = f.writeBlock( str.data(), str.length() );
331 if ( total_written != int(str.length()) ) {
332 f.close();
333 QFile::remove( strNewFile );
334 return false;
335 }
336 buf = "";
337 }
338
339 buf += "</Tasks>\n";
340 str = buf.utf8();
341 total_written = f.writeBlock( str.data(), str.length() );
342 if ( total_written != int(str.length()) ) {
343 f.close();
344 QFile::remove( strNewFile );
345 return false;
346 }
347 f.close();
348
349 // now do the rename
350 if ( ::rename( strNewFile, fn ) < 0 )
351 qWarning( "problem renaming file %s to %s errno %d",
352 strNewFile.latin1(), fn.latin1(), errno );
353
354 // remove the journal
355 QFile::remove( journalFileName() );
356 return true;
357}
358
359void TodoTable::load( const QString &fn )
360{
361 loadFile( fn, false );
362 if ( QFile::exists(journalFileName()) ) {
363 loadFile( journalFileName(), true );
364 save( fn );
365 }
366// QTable::sortColumn(2,TRUE,TRUE);
367// QTable::sortColumn(1,TRUE,TRUE);
368 QTable::sortColumn(0,TRUE,TRUE);
369 setCurrentCell( 0, 2 );
370}
371
372void TodoTable::updateVisible()
373{
374 if ( !isUpdatesEnabled() )
375 return;
376
377// qDebug("--> updateVisible!");
378
379 int visible = 0;
380 int id = mCat.id( "Todo List", showCat );
381 for ( int row = 0; row < numRows(); row++ ) {
382 CheckItem *ci = (CheckItem *)item( row, 0 );
383 Task *t = todoList[ci];
384 QArray<int> vlCats = t->categories();
385 bool hide = false;
386 if ( !showComp && ci->isChecked() )
387 hide = true;
388 if ( !showCat.isEmpty() ) {
389 if ( showCat == tr( "Unfiled" ) ) {
390 if ( vlCats.count() > 0 )
391 hide = true;
392 } else {
393 // do some comparing, we have to reverse our idea here...
394 if ( !hide ) {
395 hide = true;
396 for ( uint it = 0; it < vlCats.count(); ++it ) {
397 if ( vlCats[it] == id ) {
398 hide = false;
399 break;
400 }
401 }
402 }
403 }
404 }
405 if ( hide ) {
406 if ( currentRow() == row )
407 setCurrentCell( -1, 0 );
408 if ( rowHeight( row ) > 0 )
409 hideRow( row );
410 } else {
411 if ( rowHeight( row ) == 0 ) {
412 showRow( row );
413 adjustRow( row );
414 }
415 visible++;
416 }
417 }
418 if ( !visible )
419 setCurrentCell( -1, 0 );
420}
421
422void TodoTable::viewportPaintEvent( QPaintEvent *pe )
423{
424 if ( enablePainting )
425 QTable::viewportPaintEvent( pe );
426}
427
428void TodoTable::setPaintingEnabled( bool e )
429{
430 if ( e != enablePainting ) {
431 if ( !enablePainting ) {
432 enablePainting = true;
433 rowHeightChanged( 0 );
434 viewport()->update();
435 } else {
436 enablePainting = false;
437 }
438 }
439}
440
441void TodoTable::clear()
442{
443 for ( QMap<CheckItem*, Task *>::Iterator it = todoList.begin();
444 it != todoList.end(); ++it ) {
445 Task *todo = *it;
446 delete todo;
447 }
448 todoList.clear();
449 for ( int r = 0; r < numRows(); ++r ) {
450 for ( int c = 0; c < numCols(); ++c ) {
451 if ( cellWidget( r, c ) )
452 clearCellWidget( r, c );
453 clearCell( r, c );
454 }
455 }
456 setNumRows( 0 );
457}
458
459void TodoTable::sortColumn( int col, bool /*ascending*/, bool /*wholeRows*/ )
460{
461 // The default for wholeRows is false, however
462 // for this todo table we want to exchange complete
463 // rows when sorting. Also, we always want ascending, since
464 // the values have a logical order.
465 QTable::sortColumn( col, TRUE, TRUE );
466 updateVisible();
467}
468
469void TodoTable::slotCheckPriority(int row, int col )
470{
471 // kludgey work around to make forward along the updated priority...
472 if ( col == 1 ) {
473 // let everyone know!!
474 ComboItem* i = static_cast<ComboItem*>( item( row, col ) );
475 emit signalPriorityChanged( i->text().toInt() );
476 }
477}
478
479
480void TodoTable::updateJournal( const Task &todo, journal_action action, int row )
481{
482 QFile f( journalFileName() );
483 if ( !f.open(IO_WriteOnly|IO_Append) )
484 return;
485 QString buf;
486 QCString str;
487 buf = "<Task";
488 todo.save( buf );
489 buf += " Action=\"" + QString::number( int(action) ) + "\"";
490 buf += " Row=\"" + QString::number( row ) + "\"";
491 buf += "/>\n";
492 str = buf.utf8();
493 f.writeBlock( str.data(), str.length() );
494 f.close();
495}
496
497void TodoTable::rowHeightChanged( int row )
498{
499 if ( enablePainting )
500 QTable::rowHeightChanged( row );
501}
502
503void TodoTable::loadFile( const QString &strFile, bool fromJournal )
504{
505 QFile f( strFile );
506 if ( !f.open(IO_ReadOnly) )
507 return;
508
509 int action, row;
510 action = 0; row = 0;
511
512 enum Attribute {
513 FCompleted = 0,
514 FHasDate,
515 FPriority,
516 FCategories,
517 FDescription,
518 FDateYear,
519 FDateMonth,
520 FDateDay,
521 FUid,
522 FAction,
523 FRow
524 };
525
526 QAsciiDict<int> dict( 31 );
527 QList<Task> list;
528 dict.setAutoDelete( TRUE );
529 dict.insert( "Completed", new int(FCompleted) );
530 dict.insert( "HasDate", new int(FHasDate) );
531 dict.insert( "Priority", new int(FPriority) );
532 dict.insert( "Categories", new int(FCategories) );
533 dict.insert( "Description", new int(FDescription) );
534 dict.insert( "DateYear", new int(FDateYear) );
535 dict.insert( "DateMonth", new int(FDateMonth) );
536 dict.insert( "DateDay", new int(FDateDay) );
537 dict.insert( "Uid", new int(FUid) );
538 dict.insert( "Action", new int(FAction) );
539 dict.insert( "Row", new int(FRow) );
540
541 QByteArray ba = f.readAll();
542 f.close();
543 char* dt = ba.data();
544 int len = ba.size();
545 bool hasDueDate = FALSE;
546
547 action = ACTION_ADD;
548 int i = 0;
549 char *point;
550 while ( ( point = strstr( dt+i, "<Task " ) ) != NULL ) {
551 // new Task
552 i = point - dt;
553 Task *todo = new Task;
554 int dtY = 0, dtM = 0, dtD = 0;
555
556 i += 5;
557
558 while( 1 ) {
559 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
560 ++i;
561 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
562 break;
563 // we have another attribute, read it.
564 int j = i;
565 while ( j < len && dt[j] != '=' )
566 ++j;
567 char *attr = dt+i;
568 dt[j] = '\0';
569 i = ++j; // skip =
570 while ( i < len && dt[i] != '"' )
571 ++i;
572 j = ++i;
573 bool haveUtf = FALSE;
574 bool haveEnt = FALSE;
575 while ( j < len && dt[j] != '"' ) {
576 if ( ((unsigned char)dt[j]) > 0x7f )
577 haveUtf = TRUE;
578 if ( dt[j] == '&' )
579 haveEnt = TRUE;
580 ++j;
581 }
582 if ( i == j ) {
583 // empty value
584 i = j + 1;
585 continue;
586 }
587 QCString value( dt+i, j-i+1 );
588 i = j + 1;
589 int *lookup = dict[ attr ];
590 if ( !lookup ) {
591 todo->setCustomField(attr, value);
592 continue;
593 }
594 switch( *lookup ) {
595 case FCompleted:
596 todo->setCompleted( value.toInt() );
597 break;
598 case FHasDate:
599 // leave...
600 hasDueDate = value.toInt();
601 break;
602 case FPriority:
603 todo->setPriority( value.toInt() );
604 break;
605 case FCategories: {
606 //QString str = Qtopia::plainString( value );
607 todo->setCategories( Qtopia::Record::idsFromString( value ) );
608 break;
609 }
610 case FDescription:
611 {
612 QString str = (haveUtf ? QString::fromUtf8( value )
613 : QString::fromLatin1( value ) );
614 if ( haveEnt )
615 str = Qtopia::plainString( str );
616 todo->setDescription( str );
617 break;
618 }
619 case FDateYear:
620 dtY = value.toInt();
621 break;
622 case FDateMonth:
623 dtM = value.toInt();
624 break;
625 case FDateDay:
626 dtD = value.toInt();
627 break;
628 case FUid:
629 todo->setUid( value.toInt() );
630 break;
631 case FAction:
632 action = value.toInt();
633 break;
634 case FRow:
635 row = value.toInt();
636 break;
637 default:
638 qDebug( "huh??? missing enum? -- attr.: %s", attr );
639 break;
640 }
641 }
642
643 if ( dtY != 0 && dtM != 0 && dtD != 0 )
644 todo->setDueDate( QDate( dtY, dtM, dtD), hasDueDate );
645 else
646 todo->setHasDueDate( hasDueDate );
647
648// if ( categoryList.find( todo.category() ) == categoryList.end() )
649// categoryList.append( todo.category() );
650
651
652 // sadly we can't delay adding of items from the journal to get
653 // the proper effect, but then, the journal should _never_ be
654 // that huge
655
656 switch( action ) {
657 case ACTION_ADD:
658 if ( fromJournal ) {
659 int myrows = numRows();
660 setNumRows( myrows + 1 );
661 insertIntoTable( todo, myrows );
662 delete todo;
663 } else
664 list.append( todo );
665 break;
666 case ACTION_REMOVE:
667 journalFreeRemoveEntry( row );
668 break;
669 case ACTION_REPLACE:
670 journalFreeReplaceEntry( *todo, row );
671 delete todo;
672 break;
673 default:
674 break;
675 }
676 }
677// qDebug("parsing done=%d", t.elapsed() );
678 if ( list.count() > 0 ) {
679 internalAddEntries( list );
680 list.clear();
681 }
682// qDebug("loading done: t=%d", t.elapsed() );
683}
684
685void TodoTable::journalFreeReplaceEntry( const Task &todo, int row )
686{
687 QString strTodo;
688 strTodo = todo.description().left(40).simplifyWhiteSpace();
689 if ( row == -1 ) {
690 QMapIterator<CheckItem*, Task *> it;
691 for ( it = todoList.begin(); it != todoList.end(); ++it ) {
692 if ( *(*it) == todo ) {
693 row = it.key()->row();
694 it.key()->setChecked( todo.isCompleted() );
695 static_cast<ComboItem*>(item(row, 1))->setText( QString::number(todo.priority()) );
696 item( row, 2 )->setText( strTodo );
697 *(*it) = todo;
698 }
699 }
700 } else {
701 Task *t = todoList[static_cast<CheckItem*>(item(row, 0))];
702 todoList.remove( static_cast<CheckItem*>(item(row, 0)) );
703 delete t;
704 static_cast<CheckItem*>(item(row, 0))->setChecked( todo.isCompleted() );
705 static_cast<ComboItem*>(item(row, 1))->setText( QString::number(todo.priority()) );
706 item( row, 2 )->setText( strTodo );
707 todoList.insert( static_cast<CheckItem*>(item(row,0)), new Task(todo) );
708 }
709}
710
711void TodoTable::journalFreeRemoveEntry( int row )
712{
713 CheckItem *chk;
714 chk = static_cast<CheckItem*>(item(row, 0 ));
715 if ( !chk )
716 return;
717 todoList.remove( chk );
718
719 realignTable( row );
720}
721
722void TodoTable::keyPressEvent( QKeyEvent *e )
723{
724 if ( e->key() == Key_Space || e->key() == Key_Return ) {
725 switch ( currentColumn() ) {
726 case 0: {
727 CheckItem *i = static_cast<CheckItem*>(item(currentRow(),
728 currentColumn()));
729 if ( i )
730 i->toggle();
731 break;
732 }
733 case 1:
734 break;
735 case 2:
736 emit signalEdit();
737 default:
738 break;
739 }
740 } else {
741 QTable::keyPressEvent( e );
742 }
743}
744
745QStringList TodoTable::categories()
746{
747 // This is called seldom, so calling a load in here
748 // should be fine.
749 mCat.load( categoryFileName() );
750 QStringList categoryList = mCat.labels( "Todo List" );
751 return categoryList;
752}
753
754void TodoTable::slotDoFind( const QString &findString, bool caseSensitive,
755 bool backwards, int category )
756{
757 // we have to iterate through the table, this gives the illusion that
758 // sorting is actually being used.
759 if ( currFindRow < -1 )
760 currFindRow = currentRow() - 1;
761 clearSelection( TRUE );
762 int rows,
763 row;
764 CheckItem *chk;
765 QRegExp r( findString );
766
767 r.setCaseSensitive( caseSensitive );
768 rows = numRows();
769 static bool wrapAround = true;
770
771 if ( !backwards ) {
772 for ( row = currFindRow + 1; row < rows; row++ ) {
773 chk = static_cast<CheckItem*>( item(row, 0) );
774 if ( taskCompare(*(todoList[chk]), r, category) )
775 break;
776 }
777 } else {
778 for ( row = currFindRow - 1; row > -1; row-- ) {
779 chk = static_cast<CheckItem*>( item(row, 0) );
780 if ( taskCompare(*(todoList[chk]), r, category) )
781 break;
782 }
783 }
784 if ( row >= rows || row < 0 ) {
785 if ( row < 0 )
786 currFindRow = rows;
787 else
788 currFindRow = -1;
789 if ( wrapAround )
790 emit signalWrapAround();
791 else
792 emit signalNotFound();
793 wrapAround = !wrapAround;
794 } else {
795 currFindRow = row;
796 QTableSelection foundSelection;
797 foundSelection.init( currFindRow, 0 );
798 foundSelection.expandTo( currFindRow, numCols() - 1 );
799 addSelection( foundSelection );
800 setCurrentCell( currFindRow, numCols() - 1 );
801 // we should always be able to wrap around and find this again,
802 // so don't give confusing not found message...
803 wrapAround = true;
804 }
805}
806
807int TodoTable::showCategoryId() const
808{
809 int id;
810 id = -1;
811 // if allcategories are selected, you get unfiled...
812 if ( showCat != tr( "Unfiled" ) && showCat != tr( "All" ) )
813 id = mCat.id( "Todo List", showCat );
814 return id;
815}
816
817static bool taskCompare( const Task &task, const QRegExp &r, int category )
818{
819 bool returnMe;
820 QArray<int> cats;
821 cats = task.categories();
822
823 returnMe = false;
824 if ( (category == -1 && cats.count() == 0) || category == -2 )
825 returnMe = task.match( r );
826 else {
827 int i;
828 for ( i = 0; i < int(cats.count()); i++ ) {
829 if ( cats[i] == category ) {
830 returnMe = task.match( r );
831 break;
832 }
833 }
834 }
835 return returnMe;
836}
837
838static QString journalFileName()
839{
840 QString str;
841 str = getenv( "HOME" );
842 str += "/.todojournal";
843 return str;
844}
845
846// int TodoTable::rowHeight( int ) const
847// {
848// return 18;
849// }
850
851// int TodoTable::rowPos( int row ) const
852// {
853// return 18*row;
854// }
855
856// int TodoTable::rowAt( int pos ) const
857// {
858// return QMIN( pos/18, numRows()-1 );
859// }
diff --git a/core/pim/todo/todotable.h b/core/pim/todo/todotable.h
new file mode 100644
index 0000000..4f3a064
--- a/dev/null
+++ b/core/pim/todo/todotable.h
@@ -0,0 +1,207 @@
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#ifndef TODOTABLE_H
22#define TODOTABLE_H
23
24#include <qpe/categories.h>
25#include <qpe/stringutil.h>
26#include <qpe/task.h>
27
28#include <qtable.h>
29#include <qmap.h>
30#include <qguardedptr.h>
31
32class Node;
33class QComboBox;
34class QTimer;
35
36class CheckItem : public QTableItem
37{
38public:
39 CheckItem( QTable *t, const QString &sortkey );
40
41 void setChecked( bool b );
42 void toggle();
43 bool isChecked() const;
44 void setKey( const QString &key ) { sortKey = key; }
45 QString key() const;
46
47 void paint( QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected );
48
49private:
50 bool checked;
51 QString sortKey;
52};
53
54class ComboItem : public QTableItem
55{
56public:
57 ComboItem( QTable *t, EditType et );
58 QWidget *createEditor() const;
59 void setContentFromEditor( QWidget *w );
60 void setText( const QString &s );
61 int alignment() const { return Qt::AlignCenter; }
62
63 QString text() const;
64
65private:
66 QGuardedPtr<QComboBox> cb;
67
68};
69
70class TodoTextItem : public QTableItem
71{
72public:
73 TodoTextItem( QTable *t, const QString & str )
74 :QTableItem( t, QTableItem::Never, str ) {}
75
76 QString key () const { return Qtopia::buildSortKey( text() ); }
77};
78
79
80
81enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
82
83class TodoTable : public QTable
84{
85 Q_OBJECT
86
87public:
88 TodoTable( QWidget *parent = 0, const char * name = 0 );
89 void addEntry( const Task &todo );
90 void clearFindRow() { currFindRow = -2; }
91
92 Task currentEntry() const;
93 void replaceCurrentEntry( const Task &todo, bool fromTableItem = false );
94
95 QStringList categories();
96
97 void setShowCompleted( bool sc ) { showComp = sc; updateVisible(); }
98 bool showCompleted() const { return showComp; }
99
100 void setShowCategory( const QString &c ) { showCat = c; updateVisible(); }
101 const QString &showCategory() const { return showCat; }
102 int showCategoryId() const;
103
104 bool save( const QString &fn );
105 void load( const QString &fn );
106 void clear();
107 void removeCurrentEntry();
108
109 void setPaintingEnabled( bool e );
110
111 virtual void sortColumn( int col, bool ascending, bool /*wholeRows*/ );
112
113// int rowHeight( int ) const;
114// int rowPos( int row ) const;
115// virtual int rowAt( int pos ) const;
116
117signals:
118 void signalEdit();
119 void signalDoneChanged( bool b );
120 void signalPriorityChanged( int i );
121 void signalShowMenu( const QPoint & );
122 void signalNotFound();
123 void signalWrapAround();
124
125protected:
126 void keyPressEvent( QKeyEvent *e );
127
128private:
129 void updateVisible();
130 void viewportPaintEvent( QPaintEvent * );
131 void internalAddEntries( QList<Task> &list);
132 inline void insertIntoTable( Task *todo, int row );
133 void updateJournal( const Task &todo, journal_action action, int row = -1);
134 void mergeJournal();
135 void journalFreeReplaceEntry( const Task &todo, int row );
136 void journalFreeRemoveEntry( int row );
137 inline void realignTable( int row );
138 void loadFile( const QString &strFile, bool fromJournal = false );
139
140private slots:
141 void slotClicked( int row, int col, int button, const QPoint &pos );
142 void slotPressed( int row, int col, int button, const QPoint &pos );
143 void slotCheckPriority(int row, int col );
144 void slotCurrentChanged(int row, int col );
145 void slotDoFind( const QString &findString, bool caseSensetive,
146 bool backwards, int category );
147 void slotShowMenu();
148 void rowHeightChanged( int row );
149
150private:
151 friend class TodoWindow;
152
153 QMap<CheckItem*, Task *> todoList;
154 QStringList categoryList;
155 bool showComp;
156 QString showCat;
157 QTimer *menuTimer;
158 bool enablePainting;
159 Categories mCat;
160 int currFindRow;
161};
162
163
164inline void TodoTable::insertIntoTable( Task *todo, int row )
165{
166 QString sortKey = (char) ((todo->isCompleted() ? 'a' : 'A')
167 + todo->priority() )
168 + Qtopia::buildSortKey( todo->description() );
169 CheckItem *chk = new CheckItem( this, sortKey );
170 chk->setChecked( todo->isCompleted() );
171 ComboItem *cmb = new ComboItem( this, QTableItem::WhenCurrent );
172 cmb->setText( QString::number( todo->priority() ) );
173 QTableItem *ti = new TodoTextItem( this, todo->description().left(40).simplifyWhiteSpace() );
174 ti->setReplaceable( false );
175
176 setItem( row, 0, chk );
177 setItem( row, 1, cmb );
178 setItem( row, 2, ti );
179
180 todoList.insert( chk, todo );
181}
182
183inline void TodoTable::realignTable( int row )
184{
185 QTableItem *ti1,
186 *ti2,
187 *ti3;
188 int totalRows = numRows();
189 for ( int curr = row; curr < totalRows - 1; curr++ ) {
190 // this is bad, we must take the item out and then
191 // set it. In the end, it behaves no worse (time wise)
192 // then the old way of saving the entries to file, clearing
193 // the table re-reading in the file and resetting the table
194 ti1 = item( curr + 1, 0 );
195 ti2 = item( curr + 1, 1 );
196 ti3 = item( curr + 1, 2 );
197 takeItem( ti1 );
198 takeItem( ti2 );
199 takeItem( ti3 );
200 setItem( curr, 0, ti1 );
201 setItem( curr, 1, ti2 );
202 setItem( curr, 2, ti3 );
203 }
204 setNumRows( totalRows - 1 );
205}
206
207#endif