kpilot Library API Documentation

todoWidget.cc

00001 /* todoWidget.cc            KPilot
00002 **
00003 ** Copyright (C) 2003 by Dan Pilone
00004 ** Written 2003 by Reinhold Kainhofer
00005 **
00006 ** This file defines the todoWidget, that part of KPilot that
00007 ** displays todo records from the Pilot.
00008 */
00009 
00010 /*
00011 ** This program is free software; you can redistribute it and/or modify
00012 ** it under the terms of the GNU General Public License as published by
00013 ** the Free Software Foundation; either version 2 of the License, or
00014 ** (at your option) any later version.
00015 **
00016 ** This program is distributed in the hope that it will be useful,
00017 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 ** GNU General Public License for more details.
00020 **
00021 ** You should have received a copy of the GNU General Public License
00022 ** along with this program in a file called COPYING; if not, write to
00023 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00024 ** MA 02111-1307, USA.
00025 */
00026 
00027 /*
00028 ** Bug reports and questions can be sent to kde-pim@kde.org
00029 */
00030 static const char *todowidget_id =
00031     "$Id: todoWidget.cc,v 1.8 2003/10/13 13:58:19 kainhofe Exp $";
00032 
00033 
00034 #include "options.h"
00035 
00036 #include <qptrlist.h>
00037 #include <klistview.h>
00038 #include <qpushbutton.h>
00039 #include <qlayout.h>
00040 #include <qlabel.h>
00041 #include <qtextview.h>
00042 #include <qcombobox.h>
00043 #include <qwhatsthis.h>
00044 #include <qtextcodec.h>
00045 
00046 #include <kmessagebox.h>
00047 
00048 #include "kpilotConfig.h"
00049 #include "todoEditor.h"
00050 #include "pilotLocalDatabase.h"
00051 #include "todoWidget.moc"
00052 
00053 
00054 // This is the size of several (automatic) buffers,
00055 // used to retrieve data from the database.
00056 // I have no idea if 0xffff is some magic number or not.
00057 //
00058 //
00059 #define BUFFERSIZE  (0xffff)
00060 
00061 
00062 
00063 TodoCheckListItem::TodoCheckListItem(QListView*parent, const QString&text,
00064     recordid_t pilotid, void*r):PilotCheckListItem(parent, text, pilotid, r)
00065 {
00066 
00067 }
00068 
00069 void TodoCheckListItem::stateChange(bool state)
00070 {
00071     TodoListView*par=dynamic_cast<TodoListView*>(listView());
00072     if (par) par->itemWasChecked(this, state);
00073 }
00074 
00075 
00076 
00077 TodoWidget::TodoWidget(QWidget * parent,
00078     const QString & path) :
00079     PilotComponent(parent, "component_todo", path),
00080     fTodoInfo(0),
00081     fTodoDB(0),
00082     fPendingTodos(0)
00083 {
00084     FUNCTIONSETUP;
00085 
00086     setupWidget();
00087     fTodoList.setAutoDelete(true);
00088 
00089     /* NOTREACHED */
00090     (void) todowidget_id;
00091 }
00092 
00093 TodoWidget::~TodoWidget()
00094 {
00095     FUNCTIONSETUP;
00096     KPILOT_DELETE( fTodoDB );
00097 }
00098 
00099 int TodoWidget::getAllTodos(PilotDatabase * todoDB)
00100 {
00101     FUNCTIONSETUP;
00102 
00103     int currentRecord = 0;
00104     PilotRecord *pilotRec;
00105     PilotTodoEntry *todo;
00106     bool showSecrets = KPilotConfig::getConfig().getShowSecrets();
00107 
00108 
00109 #ifdef DEBUG
00110     DEBUGKPILOT << fname << ": Reading ToDoDB..." << endl;
00111 #endif
00112 
00113     while ((pilotRec = todoDB->readRecordByIndex(currentRecord)) != 0L)
00114     {
00115         if (!(pilotRec->isDeleted()) &&
00116             (!(pilotRec->isSecret()) || showSecrets))
00117         {
00118             todo = new PilotTodoEntry(fTodoAppInfo, pilotRec);
00119             if (todo == 0L)
00120             {
00121                 kdWarning() << k_funcinfo
00122                     << ": Couldn't allocate record "
00123                     << currentRecord++
00124                     << endl;
00125                 break;
00126             }
00127             fTodoList.append(todo);
00128         }
00129         KPILOT_DELETE( pilotRec );
00130 
00131         currentRecord++;
00132     }
00133 
00134 #ifdef DEBUG
00135     DEBUGKPILOT << fname
00136         << ": Total " << currentRecord << " records" << endl;
00137 #endif
00138 
00139     return currentRecord;
00140 }
00141 
00142 void TodoWidget::showComponent()
00143 {
00144     FUNCTIONSETUP;
00145     if ( fPendingTodos>0 ) return;
00146 
00147 #ifdef DEBUG
00148     DEBUGKPILOT << fname
00149         << ": Reading from directory " << dbPath() << endl;
00150 #endif
00151 
00152     fTodoDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
00153     unsigned char buffer[BUFFERSIZE];
00154     int appLen;
00155 
00156     fTodoList.clear();
00157 
00158     if (fTodoDB->isDBOpen())
00159     {
00160         appLen = fTodoDB->readAppBlock(buffer, BUFFERSIZE);
00161         unpack_ToDoAppInfo(&fTodoAppInfo, buffer, appLen);
00162 
00163         populateCategories(fCatList, &fTodoAppInfo.category);
00164         getAllTodos(fTodoDB);
00165 
00166     }
00167     else
00168     {
00169         populateCategories(fCatList, 0L);
00170         kdWarning() << k_funcinfo
00171             << ": Could not open local TodoDB" << endl;
00172     }
00173 
00174     KPILOT_DELETE( fTodoDB );
00175 
00176     updateWidget();
00177 }
00178 
00179 /* virtual */ bool TodoWidget::preHotSync(QString &s)
00180 {
00181     FUNCTIONSETUP;
00182 
00183     if (fPendingTodos)
00184     {
00185 #ifdef DEBUG
00186         DEBUGKPILOT << fname
00187             << ": fPendingTodo="
00188             << fPendingTodos
00189             << endl;
00190 #endif
00191 
00192 #if KDE_VERSION<220
00193         s = i18n("There are still %1 todo editing windows open.")
00194             .arg(QString::number(fPendingTodos));
00195 #else
00196         s = i18n("There is still an todo editing window open.",
00197             "There are still %n todo editing windows open.",
00198             fPendingTodos);
00199 #endif
00200         return false;
00201     }
00202 
00203     return true;
00204 }
00205 
00206 void TodoWidget::postHotSync()
00207 {
00208     FUNCTIONSETUP;
00209 
00210     fTodoList.clear();
00211     showComponent();
00212 }
00213 
00214 void TodoWidget::hideComponent()
00215 {
00216     FUNCTIONSETUP;
00217     if ( fPendingTodos==0 )
00218     {
00219         fTodoList.clear();
00220         fListBox->clear();
00221         KPILOT_DELETE( fTodoDB );
00222     }
00223 }
00224 
00225 void TodoWidget::setupWidget()
00226 {
00227     FUNCTIONSETUP;
00228 
00229     QLabel *label;
00230     QGridLayout *grid = new QGridLayout(this, 6, 4, SPACING);
00231 
00232     fCatList = new QComboBox(this);
00233     grid->addWidget(fCatList, 0, 1);
00234     connect(fCatList, SIGNAL(activated(int)),
00235         this, SLOT(slotSetCategory(int)));
00236     QWhatsThis::add(fCatList,
00237         i18n("<qt>Select the category of todos to display here.</qt>"));
00238 
00239     label = new QLabel(i18n("Category:"), this);
00240     label->setBuddy(fCatList);
00241     grid->addWidget(label, 0, 0);
00242 
00243     fListBox = new TodoListView(this);
00244     fListBox->addColumn( i18n( "Todo Item" ) );
00245     fListBox->setAllColumnsShowFocus( TRUE );
00246     fListBox->setResizeMode( KListView::LastColumn );
00247     fListBox->setFullWidth( TRUE );
00248     fListBox->setItemsMovable( FALSE );
00249     fListBox->setItemsRenameable (TRUE);
00250     grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00251     connect(fListBox, SIGNAL(selectionChanged(QListViewItem*)),
00252         this, SLOT(slotShowTodo(QListViewItem*)));
00253     connect(fListBox, SIGNAL(doubleClicked(QListViewItem*)),
00254         this, SLOT(slotEditRecord(QListViewItem*)));
00255     connect(fListBox, SIGNAL(returnPressed(QListViewItem*)),
00256         this, SLOT(slotEditRecord(QListViewItem*)));
00257     connect(fListBox, SIGNAL(itemChecked(QCheckListItem*, bool)),
00258         this, SLOT(slotItemChecked(QCheckListItem*, bool)));
00259     connect(fListBox, SIGNAL(itemRenamed(QListViewItem*, const QString &, int)),
00260         this, SLOT(slotItemRenamed(QListViewItem*, const QString &, int)));
00261     QWhatsThis::add(fListBox,
00262         i18n("<qt>This list displays all the todos "
00263             "in the selected category. Click on "
00264             "one to display it to the right.</qt>"));
00265 
00266     label = new QLabel(i18n("Todo info:"), this);
00267     grid->addWidget(label, 0, 2);
00268 
00269     // todo info text view
00270     fTodoInfo = new QTextView(this);
00271     grid->addMultiCellWidget(fTodoInfo, 1, 4, 2, 2);
00272 
00273     QPushButton *button;
00274 
00275     fEditButton = new QPushButton(i18n("Edit Record..."), this);
00276     grid->addWidget(fEditButton, 2, 0);
00277     connect(fEditButton, SIGNAL(clicked()), this, SLOT(slotEditRecord()));
00278     QWhatsThis::add(fEditButton,
00279         i18n("<qt>You can edit a todo when it is selected.</qt>"));
00280 
00281     button = new QPushButton(i18n("New Record..."), this);
00282     grid->addWidget(button, 2, 1);
00283     connect(button, SIGNAL(clicked()), this, SLOT(slotCreateNewRecord()));
00284     QWhatsThis::add(button, i18n("<qt>Add a new todo to the todo list.</qt>"));
00285 
00286     fDeleteButton = new QPushButton(i18n("Delete Record"), this);
00287     grid->addWidget(fDeleteButton, 3, 0);
00288     connect(fDeleteButton, SIGNAL(clicked()),
00289         this, SLOT(slotDeleteRecord()));
00290     QWhatsThis::add(fDeleteButton,
00291         i18n("<qt>Delete the selected todo from the todo list.</qt>"));
00292 }
00293 
00294 void TodoWidget::updateWidget()
00295 {
00296     FUNCTIONSETUP;
00297     if (!shown) return;
00298 
00299     int listIndex = 0;
00300 
00301     int currentCatID = findSelectedCategory(fCatList,
00302         &(fTodoAppInfo.category));
00303 
00304     fListBox->clear();
00305     fTodoList.first();
00306 
00307 #ifdef DEBUG
00308     DEBUGKPILOT << fname << ": Adding records..." << endl;
00309 #endif
00310 
00311     PilotTodoEntry*todo;
00312     while (fTodoList.current())
00313     {
00314         todo=fTodoList.current();
00315         if ((currentCatID == -1) ||
00316             (todo->getCat() == currentCatID))
00317         {
00318             QString title = todo->getDescription();
00319 
00320             TodoCheckListItem*item=new TodoCheckListItem(fListBox, title,
00321                 listIndex, todo);
00322             item->setOn(todo->getComplete());
00323         }
00324         listIndex++;
00325         fTodoList.next();
00326     }
00327 
00328 #ifdef DEBUG
00329     DEBUGKPILOT << fname << ": " << listIndex << " records" << endl;
00330 #endif
00331 
00332     slotUpdateButtons();
00333 }
00334 
00335 
00336 
00337 /* slot */ void TodoWidget::slotUpdateButtons()
00338 {
00339     FUNCTIONSETUP;
00340 
00341     bool enabled = (fListBox->currentItem() != 0L);
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, 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     // Response to bug 18072: Don't even try to
00394     // add records to an empty or unopened database,
00395     // since we don't have the DBInfo stuff to deal with it.
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             << (int) myDB
00409             << " with status "
00410             << ( myDB ? myDB->isDBOpen() : false )
00411             << endl;
00412 #endif
00413 
00414         KMessageBox::sorry(this,
00415             i18n("You can't add todos to the todo list "
00416                 "until you have done a HotSync at least once "
00417                 "to retrieve the database layout from your Pilot."),
00418             i18n("Can't Add New Todo"));
00419 
00420         if (myDB)
00421             KPILOT_DELETE( myDB );
00422 
00423         return;
00424     }
00425 
00426     TodoEditor *editor = new TodoEditor(0L,
00427         &fTodoAppInfo, 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.category), true);
00445 
00446 
00447     todo->setCat(currentCatID);
00448     fTodoList.append(todo);
00449     writeTodo(todo);
00450     // TODO: Just add the new record to the lists
00451     updateWidget();
00452 
00453     // k holds the item number of the todo just added.
00454     //
00455 //  int k = fListBox->count() - 1;
00456 //
00457 //  fListBox->setCurrentItem(k);    // Show the newest one
00458 //  fListBox->setBottomItem(k);
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     // TODO: Just change the record
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?")) == KMessageBox::No)
00512         return;
00513 
00514     selectedRecord->makeDeleted();
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     // Open a database (myDB) only if needed,
00551     // i.e. only if the passed-in todoDB
00552     // isn't valid.
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     // Still no valid todo database...
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     // Do the actual work.
00578     PilotRecord *pilotRec = which->pack();
00579 
00580     myDB->writeRecord(pilotRec);
00581     markDBDirty("ToDoDB");
00582     KPILOT_DELETE(pilotRec);
00583 
00584 
00585     // Clean up in the case that we allocated our own DB.
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 }
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:50 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003