00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "options.h"
00031
00032 #include <qptrlist.h>
00033 #include <klistview.h>
00034 #include <qpushbutton.h>
00035 #include <qlayout.h>
00036 #include <qlabel.h>
00037 #include <qtextview.h>
00038 #include <qcombobox.h>
00039 #include <qwhatsthis.h>
00040 #include <qtextcodec.h>
00041
00042 #include <kmessagebox.h>
00043
00044 #include "kpilotConfig.h"
00045 #include "todoEditor.h"
00046 #include "pilotLocalDatabase.h"
00047 #include "todoWidget.moc"
00048
00049
00050
00051
00052 TodoCheckListItem::TodoCheckListItem(QListView*parent, const QString&text,
00053 recordid_t pilotid, void*r):PilotCheckListItem(parent, text, pilotid, r)
00054 {
00055
00056 }
00057
00058 void TodoCheckListItem::stateChange(bool state)
00059 {
00060 TodoListView*par=dynamic_cast<TodoListView*>(listView());
00061 if (par) par->itemWasChecked(this, state);
00062 }
00063
00064
00065
00066 TodoWidget::TodoWidget(QWidget * parent,
00067 const QString & path) :
00068 PilotComponent(parent, "component_todo", path),
00069 fTodoInfo(0L),
00070 fTodoAppInfo(0L),
00071 fTodoDB(0L),
00072 fPendingTodos(0)
00073 {
00074 FUNCTIONSETUP;
00075
00076 setupWidget();
00077 fTodoList.setAutoDelete(true);
00078
00079 }
00080
00081 TodoWidget::~TodoWidget()
00082 {
00083 FUNCTIONSETUP;
00084 KPILOT_DELETE( fTodoDB );
00085 }
00086
00087 int TodoWidget::getAllTodos(PilotDatabase * todoDB)
00088 {
00089 FUNCTIONSETUP;
00090
00091 int currentRecord = 0;
00092 PilotRecord *pilotRec;
00093 PilotTodoEntry *todo;
00094
00095 #ifdef DEBUG
00096 DEBUGKPILOT << fname << ": Reading ToDoDB..." << endl;
00097 #endif
00098
00099 while ((pilotRec = todoDB->readRecordByIndex(currentRecord)) != 0L)
00100 {
00101 if (!(pilotRec->isDeleted()) &&
00102 (!(pilotRec->isSecret()) || KPilotSettings::showSecrets()))
00103 {
00104 todo = new PilotTodoEntry(pilotRec);
00105 if (todo == 0L)
00106 {
00107 WARNINGKPILOT << "Couldn't allocate record "
00108 << currentRecord++
00109 << endl;
00110 break;
00111 }
00112 fTodoList.append(todo);
00113 }
00114 KPILOT_DELETE( pilotRec );
00115
00116 currentRecord++;
00117 }
00118
00119 #ifdef DEBUG
00120 DEBUGKPILOT << fname
00121 << ": Total " << currentRecord << " records" << endl;
00122 #endif
00123
00124 return currentRecord;
00125 }
00126
00127 void TodoWidget::showComponent()
00128 {
00129 FUNCTIONSETUP;
00130 if ( fPendingTodos>0 ) return;
00131
00132 #ifdef DEBUG
00133 DEBUGKPILOT << fname
00134 << ": Reading from directory " << dbPath() << endl;
00135 #endif
00136
00137 fTodoDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
00138
00139 fTodoList.clear();
00140
00141 if (fTodoDB->isOpen())
00142 {
00143 KPILOT_DELETE(fTodoAppInfo);
00144 fTodoAppInfo = new PilotToDoInfo(fTodoDB);
00145 populateCategories(fCatList, fTodoAppInfo->categoryInfo());
00146 getAllTodos(fTodoDB);
00147
00148 }
00149 else
00150 {
00151 populateCategories(fCatList, 0L);
00152 WARNINGKPILOT << "Could not open local TodoDB" << endl;
00153 }
00154
00155 KPILOT_DELETE( fTodoDB );
00156
00157 updateWidget();
00158 }
00159
00160 bool TodoWidget::preHotSync(QString &s)
00161 {
00162 FUNCTIONSETUP;
00163
00164 if (fPendingTodos)
00165 {
00166 #ifdef DEBUG
00167 DEBUGKPILOT << fname
00168 << ": fPendingTodo="
00169 << fPendingTodos
00170 << endl;
00171 #endif
00172
00173 #if KDE_VERSION<220
00174 s = i18n("There are still %1 to-do editing windows open.")
00175 .arg(QString::number(fPendingTodos));
00176 #else
00177 s = i18n("There is still a to-do editing window open.",
00178 "There are still %n to-do editing windows open.",
00179 fPendingTodos);
00180 #endif
00181 return false;
00182 }
00183
00184 return true;
00185 }
00186
00187 void TodoWidget::postHotSync()
00188 {
00189 FUNCTIONSETUP;
00190
00191 fTodoList.clear();
00192 showComponent();
00193 }
00194
00195 void TodoWidget::hideComponent()
00196 {
00197 FUNCTIONSETUP;
00198 if ( fPendingTodos==0 )
00199 {
00200 fTodoList.clear();
00201 fListBox->clear();
00202 KPILOT_DELETE( fTodoDB );
00203 }
00204 }
00205
00206 void TodoWidget::setupWidget()
00207 {
00208 FUNCTIONSETUP;
00209
00210 QLabel *label;
00211 QGridLayout *grid = new QGridLayout(this, 6, 4, SPACING);
00212
00213 fCatList = new QComboBox(this);
00214 grid->addWidget(fCatList, 0, 1);
00215 connect(fCatList, SIGNAL(activated(int)),
00216 this, SLOT(slotSetCategory(int)));
00217 QWhatsThis::add(fCatList,
00218 i18n("<qt>Select the category of to-dos to display here.</qt>"));
00219
00220 label = new QLabel(i18n("Category:"), this);
00221 label->setBuddy(fCatList);
00222 grid->addWidget(label, 0, 0);
00223
00224 fListBox = new TodoListView(this);
00225 fListBox->addColumn( i18n( "To-do Item" ) );
00226 fListBox->setAllColumnsShowFocus( TRUE );
00227 fListBox->setResizeMode( KListView::LastColumn );
00228 fListBox->setFullWidth( TRUE );
00229 fListBox->setItemsMovable( FALSE );
00230 fListBox->setItemsRenameable (TRUE);
00231 grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00232 connect(fListBox, SIGNAL(selectionChanged(QListViewItem*)),
00233 this, SLOT(slotShowTodo(QListViewItem*)));
00234 connect(fListBox, SIGNAL(doubleClicked(QListViewItem*)),
00235 this, SLOT(slotEditRecord(QListViewItem*)));
00236 connect(fListBox, SIGNAL(returnPressed(QListViewItem*)),
00237 this, SLOT(slotEditRecord(QListViewItem*)));
00238 connect(fListBox, SIGNAL(itemChecked(QCheckListItem*, bool)),
00239 this, SLOT(slotItemChecked(QCheckListItem*, bool)));
00240 connect(fListBox, SIGNAL(itemRenamed(QListViewItem*, const QString &, int)),
00241 this, SLOT(slotItemRenamed(QListViewItem*, const QString &, int)));
00242 QWhatsThis::add(fListBox,
00243 i18n("<qt>This list displays all the to-dos "
00244 "in the selected category. Click on "
00245 "one to display it to the right.</qt>"));
00246
00247 label = new QLabel(i18n("To-do info:"), this);
00248 grid->addWidget(label, 0, 2);
00249
00250
00251 fTodoInfo = new QTextView(this);
00252 grid->addMultiCellWidget(fTodoInfo, 1, 4, 2, 2);
00253
00254 QPushButton *button;
00255 QString wt;
00256
00257 fEditButton = new QPushButton(i18n("Edit Record..."), this);
00258 grid->addWidget(fEditButton, 2, 0);
00259 connect(fEditButton, SIGNAL(clicked()), this, SLOT(slotEditRecord()));
00260
00261 wt = KPilotSettings::internalEditors() ?
00262 i18n("<qt>You can edit a to-do when it is selected.</qt>") :
00263 i18n("<qt><i>Editing is disabled by the 'internal editors' setting.</i></qt>");
00264 QWhatsThis::add(fEditButton,wt);
00265
00266 button = new QPushButton(i18n("New Record..."), this);
00267 grid->addWidget(button, 2, 1);
00268 connect(button, SIGNAL(clicked()), this, SLOT(slotCreateNewRecord()));
00269 wt = KPilotSettings::internalEditors() ?
00270 i18n("<qt>Add a new to-do to the to-do list.</qt>") :
00271 i18n("<qt><i>Adding new to-dos is disabled by the 'internal editors' setting.</i></qt>");
00272 QWhatsThis::add(button, wt);
00273 button->setEnabled(KPilotSettings::internalEditors());
00274
00275 fDeleteButton = new QPushButton(i18n("Delete Record"), this);
00276 grid->addWidget(fDeleteButton, 3, 0);
00277 connect(fDeleteButton, SIGNAL(clicked()),
00278 this, SLOT(slotDeleteRecord()));
00279 wt = KPilotSettings::internalEditors() ?
00280 i18n("<qt>Delete the selected to-do from the to-do list.</qt>") :
00281 i18n("<qt><i>Deleting is disabled by the 'internal editors' setting.</i></qt>") ;
00282 QWhatsThis::add(fDeleteButton,wt);
00283 }
00284
00285 void TodoWidget::updateWidget()
00286 {
00287 FUNCTIONSETUP;
00288 if (!shown || !fTodoAppInfo ) return;
00289
00290 int listIndex = 0;
00291
00292 int currentCatID = findSelectedCategory(fCatList,
00293 fTodoAppInfo->categoryInfo());
00294
00295 fListBox->clear();
00296 fTodoList.first();
00297
00298 #ifdef DEBUG
00299 DEBUGKPILOT << fname << ": Adding records..." << endl;
00300 #endif
00301
00302 PilotTodoEntry*todo;
00303 while (fTodoList.current())
00304 {
00305 todo=fTodoList.current();
00306 if ((currentCatID == -1) ||
00307 (todo->category() == currentCatID))
00308 {
00309 QString title = todo->getDescription();
00310
00311 TodoCheckListItem*item=new TodoCheckListItem(fListBox, title,
00312 listIndex, todo);
00313 item->setOn(todo->getComplete());
00314 }
00315 listIndex++;
00316 fTodoList.next();
00317 }
00318
00319 #ifdef DEBUG
00320 DEBUGKPILOT << fname << ": " << listIndex << " records" << endl;
00321 #endif
00322
00323 slotUpdateButtons();
00324 }
00325
00326
00327
00328 void TodoWidget::slotUpdateButtons()
00329 {
00330 FUNCTIONSETUP;
00331
00332 bool enabled = (fListBox->currentItem() != 0L);
00333
00334 enabled &= KPilotSettings::internalEditors() ;
00335
00336 fEditButton->setEnabled(enabled);
00337 fDeleteButton->setEnabled(enabled);
00338 }
00339
00340 void TodoWidget::slotSetCategory(int)
00341 {
00342 FUNCTIONSETUP;
00343
00344 updateWidget();
00345 }
00346
00347 void TodoWidget::slotEditRecord()
00348 {
00349 slotEditRecord(fListBox->currentItem());
00350 }
00351 void TodoWidget::slotEditRecord(QListViewItem*item)
00352 {
00353 FUNCTIONSETUP;
00354 if (!shown) return;
00355
00356 TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
00357 if (!p) return;
00358 PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
00359
00360 if (selectedRecord->id() == 0)
00361 {
00362 KMessageBox::error(0L,
00363 i18n("Cannot edit new records until "
00364 "HotSynced with Pilot."),
00365 i18n("HotSync Required"));
00366 return;
00367 }
00368
00369 TodoEditor *editor = new TodoEditor(selectedRecord,
00370 fTodoAppInfo->info(), this);
00371
00372 connect(editor, SIGNAL(recordChangeComplete(PilotTodoEntry *)),
00373 this, SLOT(slotUpdateRecord(PilotTodoEntry *)));
00374 connect(editor, SIGNAL(cancelClicked()),
00375 this, SLOT(slotEditCancelled()));
00376 editor->show();
00377
00378 fPendingTodos++;
00379 }
00380
00381 void TodoWidget::slotCreateNewRecord()
00382 {
00383 FUNCTIONSETUP;
00384 if (!shown) return;
00385
00386
00387
00388
00389
00390
00391 PilotDatabase *myDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
00392
00393 if (!myDB || !myDB->isOpen())
00394 {
00395 #ifdef DEBUG
00396 DEBUGKPILOT << fname
00397 << ": Tried to open "
00398 << dbPath()
00399 << "/ToDoDB"
00400 << " and got pointer @"
00401 << (void *) myDB
00402 << " with status "
00403 << ( myDB ? myDB->isOpen() : false )
00404 << endl;
00405 #endif
00406
00407 KMessageBox::sorry(this,
00408 i18n("You cannot add to-dos to the to-do list "
00409 "until you have done a HotSync at least once "
00410 "to retrieve the database layout from your Pilot."),
00411 i18n("Cannot Add New To-do"));
00412
00413 if (myDB)
00414 KPILOT_DELETE( myDB );
00415
00416 return;
00417 }
00418
00419 TodoEditor *editor = new TodoEditor(0L,
00420 fTodoAppInfo->info(), this);
00421
00422 connect(editor, SIGNAL(recordChangeComplete(PilotTodoEntry *)),
00423 this, SLOT(slotAddRecord(PilotTodoEntry *)));
00424 connect(editor, SIGNAL(cancelClicked()),
00425 this, SLOT(slotEditCancelled()));
00426 editor->show();
00427
00428 fPendingTodos++;
00429 }
00430
00431 void TodoWidget::slotAddRecord(PilotTodoEntry * todo)
00432 {
00433 FUNCTIONSETUP;
00434 if ( !shown && fPendingTodos==0 ) return;
00435
00436 int currentCatID = findSelectedCategory(fCatList,
00437 fTodoAppInfo->categoryInfo(), true);
00438
00439
00440 todo->PilotRecordBase::setCategory(currentCatID);
00441 fTodoList.append(todo);
00442 writeTodo(todo);
00443
00444 updateWidget();
00445
00446
00447
00448
00449
00450
00451
00452
00453 fPendingTodos--;
00454 if ( !shown && fPendingTodos==0 ) hideComponent();
00455 }
00456
00457 void TodoWidget::slotUpdateRecord(PilotTodoEntry * todo)
00458 {
00459 FUNCTIONSETUP;
00460 if ( !shown && fPendingTodos==0 ) return;
00461
00462 writeTodo(todo);
00463 TodoCheckListItem* currentRecord = static_cast<TodoCheckListItem*>(fListBox->currentItem());
00464
00465
00466 updateWidget();
00467 fListBox->setCurrentItem(currentRecord);
00468
00469 emit(recordChanged(todo));
00470
00471 fPendingTodos--;
00472 if ( !shown && fPendingTodos==0 ) hideComponent();
00473 }
00474
00475 void TodoWidget::slotEditCancelled()
00476 {
00477 FUNCTIONSETUP;
00478
00479 fPendingTodos--;
00480 if ( !shown && fPendingTodos==0 ) hideComponent();
00481 }
00482
00483 void TodoWidget::slotDeleteRecord()
00484 {
00485 FUNCTIONSETUP;
00486 if (!shown) return;
00487
00488 TodoCheckListItem* p = static_cast<TodoCheckListItem*>(fListBox->currentItem());
00489 if (p == 0L) return;
00490
00491 PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
00492
00493 if (selectedRecord->id() == 0)
00494 {
00495 KMessageBox::error(this,
00496 i18n("New records cannot be deleted until "
00497 "HotSynced with pilot."),
00498 i18n("HotSync Required"));
00499 return;
00500 }
00501
00502 if (KMessageBox::questionYesNo(this,
00503 i18n("Delete currently selected record?"),
00504 i18n("Delete Record?"), KStdGuiItem::del(), KStdGuiItem::cancel()) == KMessageBox::No)
00505 return;
00506
00507 selectedRecord->setDeleted(true);
00508 writeTodo(selectedRecord);
00509 emit(recordChanged(selectedRecord));
00510 showComponent();
00511 }
00512
00513
00514
00515 void TodoWidget::slotShowTodo(QListViewItem*item)
00516 {
00517 FUNCTIONSETUP;
00518 if (!shown) return;
00519
00520 TodoCheckListItem *p = dynamic_cast<TodoCheckListItem*>(item);
00521 if (!p) return;
00522 PilotTodoEntry *todo = (PilotTodoEntry *) p->rec();
00523
00524 #ifdef DEBUG
00525 DEBUGKPILOT << fname << ": Showing "<< todo->getDescription()<<endl;
00526 #endif
00527
00528 QString text(CSL1("<qt>"));
00529 text += todo->getTextRepresentation(Qt::RichText);
00530 text += CSL1("</qt>\n");
00531 fTodoInfo->setText(text);
00532
00533 slotUpdateButtons();
00534 }
00535
00536
00537
00538 void TodoWidget::writeTodo(PilotTodoEntry * which,
00539 PilotDatabase * todoDB)
00540 {
00541 FUNCTIONSETUP;
00542
00543
00544
00545
00546
00547
00548 PilotDatabase *myDB = todoDB;
00549 bool usemyDB = false;
00550
00551 if (myDB == 0L || !myDB->isOpen())
00552 {
00553 myDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
00554 usemyDB = true;
00555 }
00556
00557
00558
00559
00560 if (!myDB->isOpen())
00561 {
00562 #ifdef DEBUG
00563 DEBUGKPILOT << fname << ": Todo database is not open" <<
00564 endl;
00565 #endif
00566 return;
00567 }
00568
00569
00570
00571 PilotRecord *pilotRec = which->pack();
00572
00573 myDB->writeRecord(pilotRec);
00574 markDBDirty(CSL1("ToDoDB"));
00575 KPILOT_DELETE(pilotRec);
00576
00577
00578
00579
00580
00581 if (usemyDB)
00582 {
00583 KPILOT_DELETE(myDB);
00584 }
00585 }
00586
00587 void TodoWidget::slotItemChecked(QCheckListItem*item, bool on)
00588 {
00589 TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
00590 if (!p) return;
00591 PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
00592 if (!selectedRecord) return;
00593 selectedRecord->setComplete(on);
00594 slotShowTodo(item);
00595 }
00596
00597 void TodoWidget::slotItemRenamed(QListViewItem*item, const QString &txt, int nr)
00598 {
00599 TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
00600 if (!p) return;
00601 PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
00602 if (!selectedRecord) return;
00603 if (nr==0)
00604 {
00605 selectedRecord->setDescription(txt);
00606 slotShowTodo(item);
00607 }
00608 }