summaryrefslogtreecommitdiffstats
path: root/kpilot/todoWidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/todoWidget.cpp')
-rw-r--r--kpilot/todoWidget.cpp608
1 files changed, 608 insertions, 0 deletions
diff --git a/kpilot/todoWidget.cpp b/kpilot/todoWidget.cpp
new file mode 100644
index 0000000..1fbbaa9
--- /dev/null
+++ b/kpilot/todoWidget.cpp
@@ -0,0 +1,608 @@
+/* KPilot
+**
+** Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+**
+** This file defines the todoWidget, that part of KPilot that
+** displays todo records from the Pilot.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <tqptrlist.h>
+#include <tdelistview.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqtextview.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtextcodec.h>
+
+#include <tdemessagebox.h>
+
+#include "kpilotConfig.h"
+#include "todoEditor.h"
+#include "pilotLocalDatabase.h"
+#include "todoWidget.moc"
+
+
+
+
+TodoCheckListItem::TodoCheckListItem(TQListView*parent, const TQString&text,
+ recordid_t pilotid, void*r):PilotCheckListItem(parent, text, pilotid, r)
+{
+
+}
+
+void TodoCheckListItem::stateChange(bool state)
+{
+ TodoListView*par=dynamic_cast<TodoListView*>(listView());
+ if (par) par->itemWasChecked(this, state);
+}
+
+
+
+TodoWidget::TodoWidget(TQWidget * parent,
+ const TQString & path) :
+ PilotComponent(parent, "component_todo", path),
+ fTodoInfo(0L),
+ fTodoAppInfo(0L),
+ fTodoDB(0L),
+ fPendingTodos(0)
+{
+ FUNCTIONSETUP;
+
+ setupWidget();
+ fTodoList.setAutoDelete(true);
+
+}
+
+TodoWidget::~TodoWidget()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE( fTodoDB );
+}
+
+int TodoWidget::getAllTodos(PilotDatabase * todoDB)
+{
+ FUNCTIONSETUP;
+
+ int currentRecord = 0;
+ PilotRecord *pilotRec;
+ PilotTodoEntry *todo;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Reading ToDoDB..." << endl;
+#endif
+
+ while ((pilotRec = todoDB->readRecordByIndex(currentRecord)) != 0L)
+ {
+ if (!(pilotRec->isDeleted()) &&
+ (!(pilotRec->isSecret()) || KPilotSettings::showSecrets()))
+ {
+ todo = new PilotTodoEntry(pilotRec);
+ if (todo == 0L)
+ {
+ WARNINGKPILOT << "Couldn't allocate record "
+ << currentRecord++
+ << endl;
+ break;
+ }
+ fTodoList.append(todo);
+ }
+ KPILOT_DELETE( pilotRec );
+
+ currentRecord++;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Total " << currentRecord << " records" << endl;
+#endif
+
+ return currentRecord;
+}
+
+void TodoWidget::showComponent()
+{
+ FUNCTIONSETUP;
+ if ( fPendingTodos>0 ) return;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Reading from directory " << dbPath() << endl;
+#endif
+
+ fTodoDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
+
+ fTodoList.clear();
+
+ if (fTodoDB->isOpen())
+ {
+ KPILOT_DELETE(fTodoAppInfo);
+ fTodoAppInfo = new PilotToDoInfo(fTodoDB);
+ populateCategories(fCatList, fTodoAppInfo->categoryInfo());
+ getAllTodos(fTodoDB);
+
+ }
+ else
+ {
+ populateCategories(fCatList, 0L);
+ WARNINGKPILOT << "Could not open local TodoDB" << endl;
+ }
+
+ KPILOT_DELETE( fTodoDB );
+
+ updateWidget();
+}
+
+/* virtual */ bool TodoWidget::preHotSync(TQString &s)
+{
+ FUNCTIONSETUP;
+
+ if (fPendingTodos)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": fPendingTodo="
+ << fPendingTodos
+ << endl;
+#endif
+
+#if TDE_VERSION<220
+ s = i18n("There are still %1 to-do editing windows open.")
+ .arg(TQString::number(fPendingTodos));
+#else
+ s = i18n("There is still a to-do editing window open.",
+ "There are still %n to-do editing windows open.",
+ fPendingTodos);
+#endif
+ return false;
+ }
+
+ return true;
+}
+
+void TodoWidget::postHotSync()
+{
+ FUNCTIONSETUP;
+
+ fTodoList.clear();
+ showComponent();
+}
+
+void TodoWidget::hideComponent()
+{
+ FUNCTIONSETUP;
+ if ( fPendingTodos==0 )
+ {
+ fTodoList.clear();
+ fListBox->clear();
+ KPILOT_DELETE( fTodoDB );
+ }
+}
+
+void TodoWidget::setupWidget()
+{
+ FUNCTIONSETUP;
+
+ TQLabel *label;
+ TQGridLayout *grid = new TQGridLayout(this, 6, 4, SPACING);
+
+ fCatList = new TQComboBox(this);
+ grid->addWidget(fCatList, 0, 1);
+ connect(fCatList, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotSetCategory(int)));
+ TQWhatsThis::add(fCatList,
+ i18n("<qt>Select the category of to-dos to display here.</qt>"));
+
+ label = new TQLabel(i18n("Category:"), this);
+ label->setBuddy(fCatList);
+ grid->addWidget(label, 0, 0);
+
+ fListBox = new TodoListView(this);
+ fListBox->addColumn( i18n( "To-do Item" ) );
+ fListBox->setAllColumnsShowFocus( TRUE );
+ fListBox->setResizeMode( TDEListView::LastColumn );
+ fListBox->setFullWidth( TRUE );
+ fListBox->setItemsMovable( FALSE );
+ fListBox->setItemsRenameable (TRUE);
+ grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
+ connect(fListBox, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+ this, TQT_SLOT(slotShowTodo(TQListViewItem*)));
+ connect(fListBox, TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+ this, TQT_SLOT(slotEditRecord(TQListViewItem*)));
+ connect(fListBox, TQT_SIGNAL(returnPressed(TQListViewItem*)),
+ this, TQT_SLOT(slotEditRecord(TQListViewItem*)));
+ connect(fListBox, TQT_SIGNAL(itemChecked(TQCheckListItem*, bool)),
+ this, TQT_SLOT(slotItemChecked(TQCheckListItem*, bool)));
+ connect(fListBox, TQT_SIGNAL(itemRenamed(TQListViewItem*, const TQString &, int)),
+ this, TQT_SLOT(slotItemRenamed(TQListViewItem*, const TQString &, int)));
+ TQWhatsThis::add(fListBox,
+ i18n("<qt>This list displays all the to-dos "
+ "in the selected category. Click on "
+ "one to display it to the right.</qt>"));
+
+ label = new TQLabel(i18n("To-do info:"), this);
+ grid->addWidget(label, 0, 2);
+
+ // todo info text view
+ fTodoInfo = new TQTextView(this);
+ grid->addMultiCellWidget(fTodoInfo, 1, 4, 2, 2);
+
+ TQPushButton *button;
+ TQString wt;
+
+ fEditButton = new TQPushButton(i18n("Edit Record..."), this);
+ grid->addWidget(fEditButton, 2, 0);
+ connect(fEditButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotEditRecord()));
+
+ wt = KPilotSettings::internalEditors() ?
+ i18n("<qt>You can edit a to-do when it is selected.</qt>") :
+ i18n("<qt><i>Editing is disabled by the 'internal editors' setting.</i></qt>");
+ TQWhatsThis::add(fEditButton,wt);
+
+ button = new TQPushButton(i18n("New Record..."), this);
+ grid->addWidget(button, 2, 1);
+ connect(button, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotCreateNewRecord()));
+ wt = KPilotSettings::internalEditors() ?
+ i18n("<qt>Add a new to-do to the to-do list.</qt>") :
+ i18n("<qt><i>Adding new to-dos is disabled by the 'internal editors' setting.</i></qt>");
+ TQWhatsThis::add(button, wt);
+ button->setEnabled(KPilotSettings::internalEditors());
+
+ fDeleteButton = new TQPushButton(i18n("Delete Record"), this);
+ grid->addWidget(fDeleteButton, 3, 0);
+ connect(fDeleteButton, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotDeleteRecord()));
+ wt = KPilotSettings::internalEditors() ?
+ i18n("<qt>Delete the selected to-do from the to-do list.</qt>") :
+ i18n("<qt><i>Deleting is disabled by the 'internal editors' setting.</i></qt>") ;
+ TQWhatsThis::add(fDeleteButton,wt);
+}
+
+void TodoWidget::updateWidget()
+{
+ FUNCTIONSETUP;
+ if (!shown || !fTodoAppInfo ) return;
+
+ int listIndex = 0;
+
+ int currentCatID = findSelectedCategory(fCatList,
+ fTodoAppInfo->categoryInfo());
+
+ fListBox->clear();
+ fTodoList.first();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Adding records..." << endl;
+#endif
+
+ PilotTodoEntry*todo;
+ while (fTodoList.current())
+ {
+ todo=fTodoList.current();
+ if ((currentCatID == -1) ||
+ (todo->category() == currentCatID))
+ {
+ TQString title = todo->getDescription();
+
+ TodoCheckListItem*item=new TodoCheckListItem(fListBox, title,
+ listIndex, todo);
+ item->setOn(todo->getComplete());
+ }
+ listIndex++;
+ fTodoList.next();
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": " << listIndex << " records" << endl;
+#endif
+
+ slotUpdateButtons();
+}
+
+
+
+/* slot */ void TodoWidget::slotUpdateButtons()
+{
+ FUNCTIONSETUP;
+
+ bool enabled = (fListBox->currentItem() != 0L);
+
+ enabled &= KPilotSettings::internalEditors() ;
+
+ fEditButton->setEnabled(enabled);
+ fDeleteButton->setEnabled(enabled);
+}
+
+void TodoWidget::slotSetCategory(int)
+{
+ FUNCTIONSETUP;
+
+ updateWidget();
+}
+
+void TodoWidget::slotEditRecord()
+{
+ slotEditRecord(fListBox->currentItem());
+}
+void TodoWidget::slotEditRecord(TQListViewItem*item)
+{
+ FUNCTIONSETUP;
+ if (!shown) return;
+
+ TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
+ if (!p) return;
+ PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
+
+ if (selectedRecord->id() == 0)
+ {
+ KMessageBox::error(0L,
+ i18n("Cannot edit new records until "
+ "HotSynced with Pilot."),
+ i18n("HotSync Required"));
+ return;
+ }
+
+ TodoEditor *editor = new TodoEditor(selectedRecord,
+ fTodoAppInfo->info(), this);
+
+ connect(editor, TQT_SIGNAL(recordChangeComplete(PilotTodoEntry *)),
+ this, TQT_SLOT(slotUpdateRecord(PilotTodoEntry *)));
+ connect(editor, TQT_SIGNAL(cancelClicked()),
+ this, TQT_SLOT(slotEditCancelled()));
+ editor->show();
+
+ fPendingTodos++;
+}
+
+void TodoWidget::slotCreateNewRecord()
+{
+ FUNCTIONSETUP;
+ if (!shown) return;
+
+ // Response to bug 18072: Don't even try to
+ // add records to an empty or unopened database,
+ // since we don't have the DBInfo stuff to deal with it.
+ //
+ //
+ PilotDatabase *myDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
+
+ if (!myDB || !myDB->isOpen())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Tried to open "
+ << dbPath()
+ << "/ToDoDB"
+ << " and got pointer @"
+ << (void *) myDB
+ << " with status "
+ << ( myDB ? myDB->isOpen() : false )
+ << endl;
+#endif
+
+ KMessageBox::sorry(this,
+ i18n("You cannot add to-dos to the to-do list "
+ "until you have done a HotSync at least once "
+ "to retrieve the database layout from your Pilot."),
+ i18n("Cannot Add New To-do"));
+
+ if (myDB)
+ KPILOT_DELETE( myDB );
+
+ return;
+ }
+
+ TodoEditor *editor = new TodoEditor(0L,
+ fTodoAppInfo->info(), this);
+
+ connect(editor, TQT_SIGNAL(recordChangeComplete(PilotTodoEntry *)),
+ this, TQT_SLOT(slotAddRecord(PilotTodoEntry *)));
+ connect(editor, TQT_SIGNAL(cancelClicked()),
+ this, TQT_SLOT(slotEditCancelled()));
+ editor->show();
+
+ fPendingTodos++;
+}
+
+void TodoWidget::slotAddRecord(PilotTodoEntry * todo)
+{
+ FUNCTIONSETUP;
+ if ( !shown && fPendingTodos==0 ) return;
+
+ int currentCatID = findSelectedCategory(fCatList,
+ fTodoAppInfo->categoryInfo(), true);
+
+
+ todo->PilotRecordBase::setCategory(currentCatID);
+ fTodoList.append(todo);
+ writeTodo(todo);
+ // TODO: Just add the new record to the lists
+ updateWidget();
+
+ // k holds the item number of the todo just added.
+ //
+// int k = fListBox->count() - 1;
+//
+// fListBox->setCurrentItem(k); // Show the newest one
+// fListBox->setBottomItem(k);
+
+ fPendingTodos--;
+ if ( !shown && fPendingTodos==0 ) hideComponent();
+}
+
+void TodoWidget::slotUpdateRecord(PilotTodoEntry * todo)
+{
+ FUNCTIONSETUP;
+ if ( !shown && fPendingTodos==0 ) return;
+
+ writeTodo(todo);
+ TodoCheckListItem* currentRecord = static_cast<TodoCheckListItem*>(fListBox->currentItem());
+
+ // TODO: Just change the record
+ updateWidget();
+ fListBox->setCurrentItem(currentRecord);
+
+ emit(recordChanged(todo));
+
+ fPendingTodos--;
+ if ( !shown && fPendingTodos==0 ) hideComponent();
+}
+
+void TodoWidget::slotEditCancelled()
+{
+ FUNCTIONSETUP;
+
+ fPendingTodos--;
+ if ( !shown && fPendingTodos==0 ) hideComponent();
+}
+
+void TodoWidget::slotDeleteRecord()
+{
+ FUNCTIONSETUP;
+ if (!shown) return;
+
+ TodoCheckListItem* p = static_cast<TodoCheckListItem*>(fListBox->currentItem());
+ if (p == 0L) return;
+
+ PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
+
+ if (selectedRecord->id() == 0)
+ {
+ KMessageBox::error(this,
+ i18n("New records cannot be deleted until "
+ "HotSynced with pilot."),
+ i18n("HotSync Required"));
+ return;
+ }
+
+ if (KMessageBox::questionYesNo(this,
+ i18n("Delete currently selected record?"),
+ i18n("Delete Record?"), KStdGuiItem::del(), KStdGuiItem::cancel()) == KMessageBox::No)
+ return;
+
+ selectedRecord->setDeleted(true);
+ writeTodo(selectedRecord);
+ emit(recordChanged(selectedRecord));
+ showComponent();
+}
+
+
+
+void TodoWidget::slotShowTodo(TQListViewItem*item)
+{
+ FUNCTIONSETUP;
+ if (!shown) return;
+
+ TodoCheckListItem *p = dynamic_cast<TodoCheckListItem*>(item);
+ if (!p) return;
+ PilotTodoEntry *todo = (PilotTodoEntry *) p->rec();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Showing "<< todo->getDescription()<<endl;
+#endif
+
+ TQString text(CSL1("<qt>"));
+ text += todo->getTextRepresentation(TQt::RichText);
+ text += CSL1("</qt>\n");
+ fTodoInfo->setText(text);
+
+ slotUpdateButtons();
+}
+
+
+
+void TodoWidget::writeTodo(PilotTodoEntry * which,
+ PilotDatabase * todoDB)
+{
+ FUNCTIONSETUP;
+
+ // Open a database (myDB) only if needed,
+ // i.e. only if the passed-in todoDB
+ // isn't valid.
+ //
+ //
+ PilotDatabase *myDB = todoDB;
+ bool usemyDB = false;
+
+ if (myDB == 0L || !myDB->isOpen())
+ {
+ myDB = new PilotLocalDatabase(dbPath(), CSL1("ToDoDB"));
+ usemyDB = true;
+ }
+
+ // Still no valid todo database...
+ //
+ //
+ if (!myDB->isOpen())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Todo database is not open" <<
+ endl;
+#endif
+ return;
+ }
+
+
+ // Do the actual work.
+ PilotRecord *pilotRec = which->pack();
+
+ myDB->writeRecord(pilotRec);
+ markDBDirty(CSL1("ToDoDB"));
+ KPILOT_DELETE(pilotRec);
+
+
+ // Clean up in the case that we allocated our own DB.
+ //
+ //
+ if (usemyDB)
+ {
+ KPILOT_DELETE(myDB);
+ }
+}
+
+void TodoWidget::slotItemChecked(TQCheckListItem*item, bool on)
+{
+ TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
+ if (!p) return;
+ PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
+ if (!selectedRecord) return;
+ selectedRecord->setComplete(on);
+ slotShowTodo(item);
+}
+
+void TodoWidget::slotItemRenamed(TQListViewItem*item, const TQString &txt, int nr)
+{
+ TodoCheckListItem*p = static_cast<TodoCheckListItem*>(item);
+ if (!p) return;
+ PilotTodoEntry *selectedRecord = (PilotTodoEntry *) p->rec();
+ if (!selectedRecord) return;
+ if (nr==0)
+ {
+ selectedRecord->setDescription(txt);
+ slotShowTodo(item);
+ }
+}