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