-rw-r--r-- | core/pim/todo/main.cpp | 1 | ||||
-rw-r--r-- | core/pim/todo/mainwindow.cpp | 16 | ||||
-rw-r--r-- | core/pim/todo/tableview.cpp | 32 | ||||
-rw-r--r-- | core/pim/todo/todomanager.cpp | 7 |
4 files changed, 22 insertions, 34 deletions
diff --git a/core/pim/todo/main.cpp b/core/pim/todo/main.cpp index d070ff8..a336ba3 100644 --- a/core/pim/todo/main.cpp +++ b/core/pim/todo/main.cpp @@ -1,48 +1,47 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "mainwindow.h" #include <opie2/odebug.h> #include <qpe/qpeapplication.h> void myMessages( QtMsgType, const char* ) { } int main( int argc, char **argv ) { qInstallMsgHandler( myMessages ); QPEApplication a( argc, argv ); QTime time; time.start(); Todo::MainWindow mw; int t = time.elapsed(); - Opie::Core::owarn << "QTime " << t/1000 << oendl; mw.setCaption( QObject::tr("Opie Todolist")); QObject::connect( &a, SIGNAL( flush() ), &mw, SLOT( slotFlush() ) ); QObject::connect( &a, SIGNAL( reload() ), &mw, SLOT( slotReload() ) ); a.showMainWidget(&mw); return a.exec(); } diff --git a/core/pim/todo/mainwindow.cpp b/core/pim/todo/mainwindow.cpp index 2002e87..9424c23 100644 --- a/core/pim/todo/mainwindow.cpp +++ b/core/pim/todo/mainwindow.cpp @@ -203,840 +203,830 @@ void MainWindow::initActions() { m_options->insertSeparator(); m_bar->insertItem( QWidget::tr("Data") ,m_edit ); m_bar->insertItem( QWidget::tr("Category"), m_catMenu ); m_bar->insertItem( QWidget::tr("Options"), m_options ); m_curQuick = new QuickEditImpl( this, m_quicktask ); addToolBar( (QToolBar *)m_curQuick->widget(), QWidget::tr( "QuickEdit" ), QMainWindow::Top, TRUE ); m_curQuick->signal()->connect( this, SLOT(slotQuickEntered() ) ); } /* m_curCat from Config */ void MainWindow::initConfig() { Config config( "todo" ); config.setGroup( "View" ); m_completed = config.readBoolEntry( "ShowComplete", TRUE ); m_curCat = config.readEntry( "Category", QString::null ); m_deadline = config.readBoolEntry( "ShowDeadLine", TRUE); m_overdue = config.readBoolEntry("ShowOverDue", FALSE ); m_quicktask = config.readBoolEntry("ShowQuickTask", TRUE); } void MainWindow::initUI() { m_stack = new Opie::Ui::OWidgetStack(this, "main stack"); setCentralWidget( m_stack ); setToolBarsMovable( FALSE ); QToolBar *menubarholder = new QToolBar( this ); menubarholder->setHorizontalStretchable( TRUE ); m_bar = new QMenuBar( menubarholder ); m_tool = new QToolBar( this ); /** QPopupMenu */ m_edit = new QPopupMenu( this ); m_options = new QPopupMenu( this ); m_catMenu = new QPopupMenu( this ); m_template = new QPopupMenu( this ); m_catMenu->setCheckable( TRUE ); m_template->setCheckable( TRUE ); connect(m_catMenu, SIGNAL(activated(int) ), this, SLOT(setCategory(int) ) ); connect(m_template, SIGNAL(activated(int) ), this, SLOT(slotNewFromTemplate(int) ) ); } void MainWindow::initViews() { TableView* tableView = new TableView( this, m_stack ); QWhatsThis::add( tableView, QWidget::tr( "This is a listing of all current tasks.\n\nThe list displays the following information:\n1. Completed - A green checkmark indicates task is completed. Click here to complete a task.\n2. Priority - a graphical representation of task priority. Double-click here to modify.\n3. Description - description of task. Click here to select the task.\n4. Deadline - shows when task is due. This column can be shown or hidden by selecting Options->'Show task deadlines' from the menu above." ) ); m_stack->addWidget( tableView, m_counter++ ); m_views.append( tableView ); m_curView = tableView; connectBase( tableView ); /* add QString type + QString configname to * the View menu * and subdirs for multiple views */ } void MainWindow::initEditor() { m_curEdit = new Editor(); } void MainWindow::initShow() { m_curShow = new TextViewShow(this, this); m_stack->addWidget( m_curShow->widget() , m_counter++ ); } MainWindow::~MainWindow() { delete templateManager(); } void MainWindow::connectBase( ViewBase* ) { // once templates and signals mix we'll use it again } QPopupMenu* MainWindow::contextMenu( int , bool recur ) { QPopupMenu* menu = new QPopupMenu(); m_editAction->addTo( menu ); m_deleteAction->addTo( menu ); m_duplicateAction->addTo( menu ); menu->insertSeparator(); /* * if this event recurs we allow * to detach it. * remove all */ if ( recur ) { ; // FIXME } return menu; } QPopupMenu* MainWindow::options() { - owarn << "Options" << oendl; return m_options; } QPopupMenu* MainWindow::edit() { return m_edit; } QToolBar* MainWindow::toolbar() { return m_tool; } OPimTodoAccess::List MainWindow::list()const { return m_todoMgr.list(); } OPimTodoAccess::List MainWindow::sorted( bool asc, int sortOrder ) { int cat = 0; if ( m_curCat != QWidget::tr("All Categories") ) cat = currentCatId(); if ( m_curCat == QWidget::tr("Unfiled") ) cat = -1; - owarn << " Category " << cat << " " << m_curCat << oendl; - - int filter = 1; + int filter = OPimTodoAccess::FilterCategory; if (!m_completed ) - filter |= 4; + filter |= OPimTodoAccess::DoNotShowCompleted; if (m_overdue) - filter |= 2; + filter |= OPimTodoAccess::OnlyOverDue; return m_todoMgr.sorted( asc, sortOrder, filter, cat ); } OPimTodoAccess::List MainWindow::sorted( bool asc, int sortOrder, int addFilter) { int cat = 0; if ( m_curCat != QWidget::tr("All Categories") ) cat = currentCatId(); if ( m_curCat == QWidget::tr("Unfiled") ) cat = -1; return m_todoMgr.sorted(asc, sortOrder, addFilter, cat ); } OPimTodo MainWindow::event( int uid ) { return m_todoMgr.event( uid ); } bool MainWindow::isSyncing()const { return m_syncing; } TemplateManager* MainWindow::templateManager() { return m_tempManager; } Editor* MainWindow::currentEditor() { return m_curEdit; } TodoShow* MainWindow::currentShow() { return m_curShow; } void MainWindow::slotReload() { m_syncing = FALSE; m_todoMgr.reload(); currentView()->updateView( ); raiseCurrentView(); } void MainWindow::closeEvent( QCloseEvent* e ) { if (m_stack->visibleWidget() == currentShow()->widget() ) { m_showing = false; raiseCurrentView(); e->ignore(); return; } /* * we should have flushed and now we're still saving * so there is no need to flush */ if (m_syncing ) { e->accept(); return; } bool quit = false; if ( m_todoMgr.saveAll() ){ - owarn << "saved" << oendl; quit = true; }else { if ( QMessageBox::critical( this, QWidget::tr("Out of space"), QWidget::tr("Todo was unable\n" "to save your changes.\n" "Free up some space\n" "and try again.\n" "\nQuit Anyway?"), QMessageBox::Yes|QMessageBox::Escape, QMessageBox::No|QMessageBox::Default) != QMessageBox::No ) { e->accept(); quit = true; }else e->ignore(); } if (quit ) { Config config( "todo" ); config.setGroup( "View" ); config.writeEntry( "ShowComplete", showCompleted() ); config.writeEntry( "Category", currentCategory() ); config.writeEntry( "ShowDeadLine", showDeadline()); config.writeEntry( "ShowOverDue", showOverDue() ); config.writeEntry( "ShowQuickTask", showQuickTask() ); /* save templates */ templateManager()->save(); e->accept(); QTimer::singleShot(0, qApp, SLOT(closeAllWindows()) ); } } void MainWindow::populateTemplates() { m_template->clear(); QStringList list = templateManager()->templates(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { m_template->insertItem( (*it) ); } } /* * slotNewFromTemplate * We use the edit widget to do * the config but we setUid(1) * to get a new uid */ /* * first we get the name of the template * then we will use the TemplateManager */ void MainWindow::slotNewFromTemplate( int id ) { QString name = m_template->text( id ); OPimTodo event = templateManager()->templateEvent( name ); event = currentEditor()->edit(this, event ); if ( currentEditor()->accepted() ) { /* assign new todo */ event.setUid( 1 ); handleAlarms( OPimTodo(), event ); m_todoMgr.add( event ); currentView()->addEvent( event ); populateCategories(); } raiseCurrentView(); } void MainWindow::slotNew() { create(); } void MainWindow::slotDuplicate() { if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return; } OPimTodo ev = m_todoMgr.event( currentView()->current() ); /* let's generate a new uid */ ev.setUid(1); m_todoMgr.add( ev ); currentView()->addEvent( ev ); raiseCurrentView(); } void MainWindow::slotDelete() { if (!currentView()->current() ) return; if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return; } QString strName = currentView()->currentRepresentation(); if (!QPEMessageBox::confirmDelete(this, QWidget::tr("Todo"), strName ) ) return; handleAlarms( m_todoMgr.event( currentView()->current() ), OPimTodo() ); m_todoMgr.remove( currentView()->current() ); currentView()->removeEvent( currentView()->current() ); raiseCurrentView(); } void MainWindow::slotDelete(int uid ) { if( uid == 0 ) return; if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return; } OPimTodo to = m_todoMgr.event(uid); if (!QPEMessageBox::confirmDelete(this, QWidget::tr("Todo"), to.toShortText() ) ) return; handleAlarms(to, OPimTodo() ); m_todoMgr.remove( to.uid() ); currentView()->removeEvent( to.uid() ); raiseCurrentView(); } void MainWindow::slotDeleteAll() { if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return; } if ( !QPEMessageBox::confirmDelete( this, QWidget::tr( "Todo" ), QWidget::tr("all tasks?") ) ) return; m_todoMgr.removeAll(); currentView()->clear(); raiseCurrentView(); } void MainWindow::slotDeleteCompleted() { if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return; } if ( !QPEMessageBox::confirmDelete( this, QWidget::tr( "Todo" ), QWidget::tr("all completed tasks?") ) ) return; m_todoMgr.removeCompleted(); currentView()->updateView( ); } void MainWindow::slotFind() { } void MainWindow::slotEdit() { slotEdit( currentView()->current() ); } /* * set the category */ void MainWindow::setCategory( int c) { if ( c <= 0 ) return; - owarn << "Iterating over cats " << c << oendl; for ( unsigned int i = 1; i < m_catMenu->count(); i++ ) m_catMenu->setItemChecked(i, c == (int)i ); if (c == 1 ) { m_curCat = QString::null; setCaption( QWidget::tr("Todo") + " - " + QWidget::tr("All Categories" ) ); }else if ( c == (int)m_catMenu->count() - 1 ) { m_curCat = QWidget::tr("Unfiled"); setCaption( QWidget::tr("Todo") + " - " + QWidget::tr("Unfiled") ); }else { m_curCat = m_todoMgr.categories()[c-2]; setCaption( QWidget::tr("Todo") + " - " + m_curCat ); } m_catMenu->setItemChecked( c, true ); currentView()->setShowCategory( m_curCat ); raiseCurrentView(); } void MainWindow::slotShowDeadLine( bool dead) { m_deadline = dead; currentView()->setShowDeadline( dead ); } void MainWindow::slotShowCompleted( bool show) { m_completed = show; currentView()->setShowCompleted( m_completed ); } void MainWindow::slotShowQuickTask( bool show ) { m_quicktask = show; if ( m_quicktask ) m_curQuick->widget()->show(); else m_curQuick->widget()->hide(); } bool MainWindow::showOverDue()const { return m_overdue; } void MainWindow::setDocument( const QString& fi) { DocLnk doc(fi); if (doc.isValid() ) receiveFile(doc.file() ); else receiveFile(fi ); } static const char *beamfile = "/tmp/opie-todo.vcs"; void MainWindow::slotBeam() { beam( currentView()->current() ); } void MainWindow::beamDone( Ir* ir) { delete ir; ::unlink( beamfile ); } void MainWindow::receiveFile( const QString& filename ) { OPimTodoAccessVCal* cal = new OPimTodoAccessVCal(filename ); OPimTodoAccess acc( cal ); acc.load(); OPimTodoAccess::List list = acc.allRecords(); if (list.count()){ QString message = QWidget::tr("<P>%1 new tasks arrived.<p>Would you like to add them to your Todolist?").arg(list.count() ); if ( QMessageBox::information(this, QWidget::tr("New Tasks"), message, QMessageBox::Ok, QMessageBox::Cancel ) == QMessageBox::Ok ) { OPimTodoAccess::List::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) m_todoMgr.add( (*it) ); currentView()->updateView(); } } } void MainWindow::slotFlush() { m_syncing = TRUE; m_todoMgr.save(); } void MainWindow::slotShowDetails() { slotShow( currentView()->current() ); } /* * populate the Categories * Menu */ void MainWindow::populateCategories() { m_todoMgr.load(); m_catMenu->clear(); int id, rememberId; id = 1; rememberId = 1; m_catMenu->insertItem( QWidget::tr( "All Categories" ), id++ ); m_catMenu->insertSeparator(); QStringList categories = m_todoMgr.categories(); categories.append( QWidget::tr( "Unfiled" ) ); for ( QStringList::Iterator it = categories.begin(); it != categories.end(); ++it ) { m_catMenu->insertItem( *it, id ); if ( *it == currentCategory() ) rememberId = id; ++id; } setCategory( rememberId ); } bool MainWindow::showCompleted()const { return m_completed; } bool MainWindow::showDeadline()const { return m_deadline; } bool MainWindow::showQuickTask()const { return m_quicktask; } QString MainWindow::currentCategory()const { return m_curCat; } int MainWindow::currentCatId() { return m_todoMgr.catId( m_curCat ); } ViewBase* MainWindow::currentView() { return m_curView; } void MainWindow::raiseCurrentView() { // due QPE/Application/todolist show(int) // we might not have the populateCategories slot called once // we would show the otodo but then imediately switch to the currentView // if we're initially showing we shouldn't raise the table // in returnFromView we fix up m_showing if (m_showing ) return; m_stack->raiseWidget( m_curView->widget() ); } void MainWindow::slotShowDue(bool ov) { m_overdue = ov; currentView()->showOverDue( ov ); raiseCurrentView(); } void MainWindow::slotShow( int uid ) { if ( uid == 0 ) return; - owarn << "slotShow" << oendl; currentShow()->slotShow( event( uid ) ); m_stack->raiseWidget( currentShow()->widget() ); } void MainWindow::slotShowNext() { int l = currentView()->next(); if (l!=0) slotShow(l); } void MainWindow::slotShowPrev() { int l = currentView()->prev(); if (l!=0) slotShow(l); } void MainWindow::slotEdit( int uid ) { if (uid == 0 ) return; if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can't be edited, currently syncing")); return; } OPimTodo old_todo = m_todoMgr.event( uid ); OPimTodo todo = currentEditor()->edit(this, old_todo ); /* if completed */ if ( currentEditor()->accepted() ) { handleAlarms( old_todo, todo ); m_todoMgr.update( todo.uid(), todo ); currentView()->replaceEvent( todo ); /* a Category might have changed */ populateCategories(); } raiseCurrentView(); } /* void MainWindow::slotUpdate1( int uid, const SmallTodo& ev) { m_todoMgr.update( uid, ev ); } */ void MainWindow::updateTodo( const OPimTodo& ev) { m_todoMgr.update( ev.uid() , ev ); } /* The view changed it's configuration * update the view menu */ void MainWindow::slotUpdate3( QWidget* ) { } void MainWindow::updateList() { m_todoMgr.updateList(); } void MainWindow::setReadAhead( uint count ) { if (m_todoMgr.todoDB() ) m_todoMgr.todoDB()->setReadAhead( count ); } void MainWindow::slotQuickEntered() { - owarn << "entered" << oendl; OPimTodo todo = quickEditor()->todo(); if (todo.isEmpty() ) return; m_todoMgr.add( todo ); currentView()->addEvent( todo ); raiseCurrentView(); } QuickEditBase* MainWindow::quickEditor() { return m_curQuick; } void MainWindow::slotComplete( int uid ) { slotComplete( event(uid) ); } void MainWindow::slotComplete( const OPimTodo& todo ) { OPimTodo to = todo; to.setCompleted( !to.isCompleted() ); to.setCompletedDate( QDate::currentDate() ); /* * if the item does recur * we need to spin it off * and update the items duedate to the next * possible recurrance of this item... * the spinned off one will loose the * recurrence. * We calculate the difference between the old due date and the * new one and add this diff to start, completed and alarm dates * -zecke */ if ( to.hasRecurrence() && to.isCompleted() ) { OPimTodo to2( to ); /* the spinned off one won't recur anymore */ to.setRecurrence( OPimRecurrence() ); OPimRecurrence rec = to2.recurrence(); rec.setStart( to.dueDate() ); to2.setRecurrence( rec ); /* * if there is a next occurence * from the duedate of the last recurrance */ QDate date; if ( to2.recurrence().nextOcurrence( to2.dueDate().addDays(1), date ) ) { int dayDiff = to.dueDate().daysTo( date ); - owarn << "day diff is " << dayDiff << oendl; QDate inval; /* generate a new uid for the old record */ to.setUid( 1 ); /* add the old one cause it has a new UID here cause it was spin off */ m_todoMgr.add( to ); /* * update the due date * start date * and complete date */ to2.setDueDate( date ); rec.setStart( date ); to2.setRecurrence( rec ); // could be Monday, TuesDay, Thursday every week /* move start date */ if (to2.hasStartDate() ) to2.setStartDate( to2.startDate().addDays( dayDiff ) ); /* now the alarms */ if (to2.hasNotifiers() ) { OPimNotifyManager::Alarms _als = to2.notifiers().alarms(); OPimNotifyManager::Alarms als; /* for every alarm move the day */ for ( OPimNotifyManager::Alarms::Iterator it = _als.begin(); it != _als.end(); ++it ) { OPimAlarm al = (*it); al.setDateTime( al.dateTime().addDays( dayDiff ) ); als.append( al ); } to2.notifiers().setAlarms( als ); handleAlarms( OPimTodo(), todo ); } to2.setCompletedDate( inval ); to2.setCompleted( false ); updateTodo( to2 ); }else updateTodo( to ); }else updateTodo( to ); currentView()->updateView(); raiseCurrentView(); } void MainWindow::flush() { slotFlush(); } void MainWindow::reload() { slotReload(); } int MainWindow::create() { int uid = 0; if(m_syncing) { QMessageBox::warning(this, QWidget::tr("Todo"), QWidget::tr("Data can not be edited, currently syncing")); return uid; } m_todoMgr.load(); OPimTodo todo = currentEditor()->newTodo( currentCatId(), this ); if ( currentEditor()->accepted() ) { //todo.assignUid(); uid = todo.uid(); handleAlarms( OPimTodo(), todo ); m_todoMgr.add( todo ); currentView()->addEvent( todo ); // I'm afraid we must call this every time now, otherwise // spend expensive time comparing all these strings... // but only call if we changed something -zecke populateCategories(); } raiseCurrentView( ); return uid; } /* delete it silently... */ bool MainWindow::remove( int uid ) { if (m_syncing) return false; /* argh need to get the whole OEvent... to disable alarms -zecke */ handleAlarms( OPimTodo(), m_todoMgr.event( uid ) ); return m_todoMgr.remove( uid ); } void MainWindow::beam( int uid) { if( uid == 0 ) return; ::unlink( beamfile ); m_todoMgr.load(); OPimTodo todo = event( uid ); OPimTodoAccessVCal* cal = new OPimTodoAccessVCal(QString::fromLatin1(beamfile) ); OPimTodoAccess acc( cal ); acc.load(); acc.add( todo ); acc.save(); Ir* ir = new Ir(this ); connect(ir, SIGNAL(done(Ir*) ), this, SLOT(beamDone(Ir*) ) ); ir->send(beamfile, todo.summary(), "text/x-vCalendar" ); } void MainWindow::show( int uid ) { m_todoMgr.load(); // might not be loaded yet m_showing = true; slotShow( uid ); raise(); QPEApplication::setKeepRunning(); } void MainWindow::edit( int uid ) { m_todoMgr.load(); slotEdit( uid ); } void MainWindow::add( const OPimRecord& rec) { OPimTodo test; if ( rec.rtti() != test.rtti() ) return; m_todoMgr.load(); // might not be loaded const OPimTodo& todo = static_cast<const OPimTodo&>(rec); m_todoMgr.add(todo ); currentView()->addEvent( todo ); // I'm afraid we must call this every time now, otherwise // spend expensive time comparing all these strings... // but only call if we changed something -zecke populateCategories(); } void MainWindow::slotReturnFromView() { m_showing = false; raiseCurrentView(); } namespace { OPimNotifyManager::Alarms findNonMatching( const OPimNotifyManager::Alarms& oldAls, const OPimNotifyManager::Alarms& newAls ) { OPimNotifyManager::Alarms nonMatching; OPimNotifyManager::Alarms::ConstIterator oldIt = oldAls.begin(); OPimNotifyManager::Alarms::ConstIterator newIt; for ( ; oldIt != oldAls.end(); ++oldIt ) { bool found = false; QDateTime oldDt = (*oldIt).dateTime(); for (newIt= newAls.begin(); newIt != newAls.end(); ++newIt ) { if ( oldDt == (*newIt).dateTime() ) { found = true; break; } } if (!found) nonMatching.append( (*oldIt) ); } return nonMatching; } void addAlarms( const OPimNotifyManager::Alarms& als, int uid ) { OPimNotifyManager::Alarms::ConstIterator it; for ( it = als.begin(); it != als.end(); ++it ) { - owarn << "Adding alarm for " << (*it).dateTime().toString() << oendl; AlarmServer::addAlarm( (*it).dateTime(), "QPE/Application/todolist", "alarm(QDateTime,int)", uid ); } } void removeAlarms( const OPimNotifyManager::Alarms& als, int uid ) { OPimNotifyManager::Alarms::ConstIterator it; for ( it = als.begin(); it != als.end(); ++it ) { - owarn << "Removinf alarm for " << (*it).dateTime().toString() << oendl; AlarmServer::deleteAlarm( (*it).dateTime(), "QPE/Application/todolist", "alarm(QDateTime,int)", uid ); } } } void MainWindow::handleAlarms( const OPimTodo& oldTodo, const OPimTodo& newTodo) { /* * if oldTodo is not empty and has notifiers we need to find the deleted ones */ if(!oldTodo.isEmpty() && oldTodo.hasNotifiers() ) { OPimNotifyManager::Alarms removed; OPimNotifyManager::Alarms oldAls = oldTodo.notifiers().alarms(); if (!newTodo.hasNotifiers() ) removed = oldAls; else removed = findNonMatching( oldAls, newTodo.notifiers().alarms() ); removeAlarms( removed, oldTodo.uid() ); } if ( newTodo.hasNotifiers() ) { OPimNotifyManager::Alarms added; if ( oldTodo.isEmpty() || !oldTodo.hasNotifiers() ) added = newTodo.notifiers().alarms(); else added = findNonMatching( newTodo.notifiers().alarms(), oldTodo.notifiers().alarms() ); addAlarms( added, newTodo.uid() ); } } /* we might have not loaded the db */ void MainWindow::doAlarm( const QDateTime& dt, int uid ) { m_todoMgr.load(); OPimTodo todo = m_todoMgr.event( uid ); if (!todo.hasNotifiers() ) return; /* * let's find the right alarm and find out if silent * then show a richtext widget */ bool loud = false; OPimNotifyManager::Alarms als = todo.notifiers().alarms(); OPimNotifyManager::Alarms::Iterator it; for ( it = als.begin(); it != als.end(); ++it ) { if ( (*it).dateTime() == dt ) { loud = ( (*it).sound() == OPimAlarm::Loud ); break; } } if (loud) startAlarm(); QDialog dlg(this, 0, TRUE ); QVBoxLayout* lay = new QVBoxLayout( &dlg ); QTextView* view = new QTextView( &dlg ); lay->addWidget( view ); QPushButton* btnOk = new QPushButton( tr("Ok"), &dlg ); connect( btnOk, SIGNAL(clicked() ), &dlg, SLOT(accept() ) ); lay->addWidget( btnOk ); QString text = tr("<h1>Alarm at %1</h1><br>").arg( TimeString::dateString( dt ) ); text += todo.toRichText(); view->setText( text ); bool needToStay = QPEApplication::execDialog( &dlg ); if (loud) killAlarm(); if (needToStay) { // showMaximized(); // raise(); QPEApplication::setKeepRunning(); // setActiveWindow(); } } diff --git a/core/pim/todo/tableview.cpp b/core/pim/todo/tableview.cpp index b7458d8..221faca 100644 --- a/core/pim/todo/tableview.cpp +++ b/core/pim/todo/tableview.cpp @@ -45,596 +45,600 @@ #include "tableview.h" using namespace Todo; namespace { static const int BoxSize = 14; static const int RowHeight = 20; } TableView::EditorWidget::EditorWidget() : m_wid(0l), m_row(-1), m_col(-1) { } void TableView::EditorWidget::setCellWidget(QWidget* wid, int row, int col ) { m_wid = wid; m_row = row; m_col = col; } void TableView::EditorWidget::releaseCellWidget() { m_wid = 0; m_row = m_col = -1; } QWidget* TableView::EditorWidget::cellWidget()const { return m_wid; } int TableView::EditorWidget::cellRow()const { return m_row; } int TableView::EditorWidget::cellCol()const { return m_col; } void TableView::initConfig() { Config config( "todo" ); config.setGroup( "Options" ); m_completeStrokeWidth = config.readNumEntry( "CompleteStrokeWidth", 8 ); for (int i = 0; i < numCols(); i++ ) { int width = config.readNumEntry("Width"+QString::number(i), -1 ); setColumnWidth(i, width == -1 ? columnWidth(i) : width ); } } TableView::TableView( MainWindow* window, QWidget* wid ) : QTable( wid ), TodoView( window ) { setName("TableView"); // Load icons // TODO - probably should be done globally somewhere else, // see also quickeditimpl.cpp/h, taskeditoroverview.cpp/h m_pic_completed = Resource::loadPixmap( "todo/completed" ); QString namestr; for ( unsigned int i = 1; i < 6; i++ ) { namestr = "todo/priority"; namestr.append( QString::number( i ) ); m_pic_priority[ i - 1 ] = Resource::loadPixmap( namestr ); } setUpdatesEnabled( false ); viewport()->setUpdatesEnabled( false ); m_enablePaint = false; setNumRows(0); setNumCols(4); horizontalHeader()->setLabel( 0, QWidget::tr("C.") ); horizontalHeader()->setLabel( 1, QWidget::tr("Priority") ); horizontalHeader()->setLabel( 2, QWidget::tr("Summary" ) ); horizontalHeader()->setLabel( 3, QWidget::tr("Deadline") ); setShowDeadline( todoWindow()->showDeadline() ); setSorting( TRUE ); setSelectionMode( NoSelection ); setLeftMargin( 0 ); verticalHeader()->hide(); connect((QTable*)this, SIGNAL( clicked(int,int,int,const QPoint&) ), this, SLOT( slotClicked(int,int,int,const QPoint&) ) ); connect((QTable*)this, SIGNAL( pressed(int,int,int,const QPoint&) ), this, SLOT( slotPressed(int,int,int,const QPoint&) ) ); connect((QTable*)this, SIGNAL(valueChanged(int,int) ), this, SLOT( slotValueChanged(int,int) ) ); connect((QTable*)this, SIGNAL(currentChanged(int,int) ), this, SLOT( slotCurrentChanged(int,int) ) ); m_menuTimer = new QTimer( this ); connect( m_menuTimer, SIGNAL(timeout()), this, SLOT(slotShowMenu()) ); /* now let's init the config */ initConfig(); m_enablePaint = true; setUpdatesEnabled( true ); viewport()->setUpdatesEnabled( true ); viewport()->update(); - setSortOrder( 0 ); + setSortOrder( Opie::OPimTodoAccess::Completed ); setAscending( TRUE ); m_first = true; } /* a new day has started * update the day */ void TableView::newDay() { clear(); updateView(); } TableView::~TableView() { Config config( "todo" ); config.setGroup( "Options" ); for (int i = 0; i < numCols(); i++ ) config.writeEntry("Width"+QString::number(i), columnWidth(i) ); } void TableView::slotShowMenu() { QPopupMenu *menu = todoWindow()->contextMenu( current(), sorted()[currentRow()].recurrence().doesRecur() ); menu->exec(QCursor::pos() ); delete menu; } QString TableView::type() const { return QString::fromLatin1( tr("Table View") ); } int TableView::current() { if (numRows() == 0 ) return 0; int uid = sorted().uidAt(currentRow() ); return uid; } int TableView::next() { if ( numRows() == 0 ) return 0; if ( currentRow() + 1 >= numRows() ) return 0; setCurrentCell( currentRow() +1, currentColumn() ); return sorted().uidAt( currentRow() ); } int TableView::prev() { if ( numRows() == 0 ) return 0; if ( currentRow() - 1 < 0 ) return 0; setCurrentCell( currentRow() -1, currentColumn() ); return sorted().uidAt( currentRow() ); } QString TableView::currentRepresentation() { OPimTodo to = sorted()[currentRow()]; return to.summary().isEmpty() ? to.description().left(20) : to.summary() ; } /* show overdue */ void TableView::showOverDue( bool ) { clear(); updateView(); } void TableView::updateView( ) { - owarn << "update view" << oendl; m_row = false; static int id; id = startTimer(4000 ); /* FIXME we want one page to be read! * * Calculate that screensize */ todoWindow()->setReadAhead( 4 ); sort(); OPimTodoAccess::List::Iterator it, end; it = sorted().begin(); end = sorted().end(); - owarn << "setTodos" << oendl; QTime time; time.start(); m_enablePaint = false; setUpdatesEnabled( false ); viewport()->setUpdatesEnabled( false ); setNumRows( it.count() ); if ( it.count() == 0 ) killTimer(id); // int elc = time.elapsed(); setUpdatesEnabled( true ); viewport()->setUpdatesEnabled( true ); viewport()->update(); m_enablePaint = true; // int el = time.elapsed(); } void TableView::setTodo( int, const OPimTodo&) { sort(); /* repaint */ repaint(); } void TableView::addEvent( const OPimTodo&) { /* fix problems of not showing the 'Haken' */ updateView(); } /* * find the event * and then replace the complete row */ void TableView::replaceEvent( const OPimTodo& ev) { addEvent( ev ); } /* * re aligning table can be slow too * FIXME: look what performs better * either this or the old align table */ void TableView::removeEvent( int ) { updateView(); } -void TableView::setShowCompleted( bool b) { - owarn << "Show Completed " << b << oendl; +void TableView::setShowCompleted( bool ) { updateView(); } void TableView::setShowDeadline( bool b ) { - owarn << "Show Deadline " << b << oendl; if ( b ) showColumn( 3 ); else hideColumn( 3 ); // Try to intelligently size columns // TODO - would use width() below, but doesn't have valid value at time of c'tor int col2width = 238; int width = m_pic_completed.width(); setColumnWidth( 0, width ); col2width -= width; width = fontMetrics().boundingRect( horizontalHeader()->label( 1 ) ).width() + 8; setColumnWidth( 1, width ); col2width -= width; if ( b ) { width = fontMetrics().boundingRect( horizontalHeader()->label( 3 ) ).width() + 8; setColumnWidth( 3, width ); col2width -= width; } setColumnWidth( 2, col2width ); } void TableView::setShowCategory( const QString& str) { - owarn << "setShowCategory" << oendl; if ( str != m_oleCat || m_first ) updateView(); m_oleCat = str; m_first = false; } void TableView::clear() { setNumRows(0); } void TableView::slotClicked(int row, int col, int, const QPoint& point) { if ( m_editorWidget.cellWidget() ) { //setCellContentFromEditor(m_editorWidget.cellRow(), m_editorWidget.cellCol() ); endEdit(m_editorWidget.cellRow(), m_editorWidget.cellCol(), true, true ); m_editorWidget.releaseCellWidget(); } if ( !cellGeometry(row, col ).contains(point ) ) return; int ui= sorted().uidAt( row ); switch( col ) { case 0:{ int x = point.x() -columnPos( col ); int y = point.y() -rowPos( row ); int w = columnWidth( col ); int h = rowHeight( row ); if ( x >= ( w - BoxSize ) / 2 && x <= ( w - BoxSize ) / 2 + BoxSize && y >= ( h - BoxSize ) / 2 && y <= ( h - BoxSize ) / 2 + BoxSize ) { TodoView::complete(sorted()[row] ); } } break; // Priority emit a double click... case 1:{ QWidget* wid = beginEdit( row, col, FALSE ); m_editorWidget.setCellWidget( wid, row, col ); } break; case 2: { m_menuTimer->stop(); showTodo( ui ); break; } case 3: { m_menuTimer->stop(); TodoView::edit( ui ); break; } } } void TableView::slotPressed(int row, int col, int, const QPoint& point) { - owarn << "pressed row " << row << " col " << col << " x:" << point.x() - << "+y:" << point.y() << oendl; m_prevP = point; /* TextColumn column */ if ( col == 2 && cellGeometry( row, col ).contains( point ) ) m_menuTimer->start( 750, TRUE ); } void TableView::slotValueChanged( int, int ) { - owarn << "Value Changed" << oendl; } void TableView::slotCurrentChanged(int, int ) { m_menuTimer->stop(); } QWidget* TableView::widget() { return this; } /* * We need to overwrite sortColumn * because we want to sort whole row * based * We event want to set the setOrder * to a sort() and update() */ void TableView::sortColumn( int col, bool asc, bool ) { - owarn << "bool " << asc << oendl; + switch(col) { + case 1: + col = Opie::OPimTodoAccess::Priority; + break; + case 2: + col = Opie::OPimTodoAccess::SortSummary; + break; + case 3: + col = Opie::OPimTodoAccess::Deadline; + break; + case 0: + default: + col = Opie::OPimTodoAccess::Completed; + break; + } + setSortOrder( col ); setAscending( asc ); updateView(); } void TableView::viewportPaintEvent( QPaintEvent* e) { if (m_enablePaint ) QTable::viewportPaintEvent( e ); } /* * This segment is copyrighted by TT * it was taken from their todolist * application this code is GPL */ void TableView::paintCell(QPainter* p, int row, int col, const QRect& cr, bool ) { const QColorGroup &cg = colorGroup(); p->save(); OPimTodo task = sorted()[row]; // TODO - give user option for grid or bars? // Paint alternating background bars if ( (row % 2 ) == 0 ) { p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) ); p->setPen( QPen( cg.text() ) ); } else { p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Background ) ); p->setPen( QPen( cg.buttonText() ) ); } // Paint grid //p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) ); //QPen op = p->pen(); //p->setPen(cg.mid()); //p->drawLine( 0, cr.height() - 1, cr.width() - 1, cr.height() - 1 ); //p->drawLine( cr.width() - 1, 0, cr.width() - 1, cr.height() - 1 ); //p->setPen(op); QFont f = p->font(); QFontMetrics fm(f); int marg = ( cr.width() - BoxSize ) / 2; int x = 0; int y = ( cr.height() - BoxSize ) / 2; switch(col) { case 0: // completed field { //p->setPen( QPen( cg.text() ) ); //p->drawRect( x + marg, y, BoxSize, BoxSize ); //p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 ); if ( task.isCompleted() ) { p->drawPixmap( x + marg, y, m_pic_completed ); } } break; case 1: // priority field { p->drawPixmap( x + marg, y, m_pic_priority[ task.priority() - 1 ] ); } break; case 2: // description field { QString text = task.summary().isEmpty() ? task.description().left(20) : task.summary(); p->drawText(2,2 + fm.ascent(), text); } break; case 3: { QString text; if (task.hasDueDate()) { int off = QDate::currentDate().daysTo( task.dueDate() ); text = tr( "%1 day(s)").arg(QString::number(off)); /* * set color if not completed */ if (!task.isCompleted() ) { QColor color = Qt::black; if ( off < 0 ) color = Qt::red; else if ( off == 0 ) color = Qt::yellow; else if ( off > 0 ) color = Qt::green; p->setPen(color ); } } else { text = tr("None"); } p->drawText(2,2 + fm.ascent(), text); } break; } p->restore(); } QWidget* TableView::createEditor(int row, int col, bool )const { switch( col ) { case 1: { /* the priority stuff */ QComboBox* combo = new QComboBox( viewport() ); for ( int i = 0; i < 5; i++ ) { combo->insertItem( m_pic_priority[ i ] ); } combo->setCurrentItem( sorted()[row].priority()-1 ); return combo; } /* summary */ case 2:{ QLineEdit* edit = new QLineEdit( viewport() ); edit->setText( sorted()[row].summary() ); return edit; } case 0: default: return 0l; } } void TableView::setCellContentFromEditor(int row, int col ) { - owarn << "set cell content from editor" << oendl; if ( col == 1 ) { QWidget* wid = cellWidget(row, 1 ); if ( wid->inherits("QComboBox") ) { int pri = ((QComboBox*)wid)->currentItem() + 1; OPimTodo todo = sorted()[row]; if ( todo.priority() != pri ) { todo.setPriority( pri ); TodoView::update( todo.uid(), todo ); updateView(); } } }else if ( col == 2) { QWidget* wid = cellWidget(row, 2); if ( wid->inherits("QLineEdit") ) { QString text = ((QLineEdit*)wid)->text(); OPimTodo todo = sorted()[row]; if ( todo.summary() != text ) { todo.setSummary( text ); TodoView::update( todo.uid(), todo ); updateView(); } } } } void TableView::slotPriority() { setCellContentFromEditor( currentRow(), currentColumn() ); } /* * We'll use the TimerEvent to read ahead or to keep the cahce always * filled enough. * We will try to read ahead 4 items in both ways * up and down. On odd or even we will currentRow()+-4 or +-9 * */ void TableView::timerEvent( QTimerEvent* ) { -// Opie::Core::owarn << "sorted " << sorted().count() << oendl; if (sorted().count() == 0 ) return; int row = currentRow(); if ( m_row ) { int ro = row-4; if (ro < 0 ) ro = 0; sorted()[ro]; ro = row+4; sorted()[ro]; } else { int ro = row + 8; sorted()[ro]; ro = row-8; if (ro < 0 ) ro = 0; sorted()[ro]; } m_row = !m_row; } // We want a strike through completed ;) // durchstreichen to complete /* * MouseTracking is off this mean we only receive * these events if the mouse button is pressed * We've the previous point saved * We check if the previous and current Point are * in the same row. * Then we check if they're some pixel horizontal away * if the distance between the two points is greater than * 8 we mark the underlying todo as completed and do a repaint * * BUG: When clicking on the Due column and it's scrollable * the todo is marked as completed... * REASON: QTable is doing auto scrolling which leads to a move * in the x coordinate and this way it's able to pass the * m_completeStrokeWidth criteria * WORKAROUND: strike through needs to strike through the same * row and two columns! */ void TableView::contentsMouseReleaseEvent( QMouseEvent* e) { int row = rowAt(m_prevP.y()); int colOld = columnAt(m_prevP.x() ); int colNew = columnAt(e->x() ); - owarn << "colNew: " << colNew << " colOld: " << colOld << oendl; if ( row == rowAt( e->y() ) && row != -1 && colOld != colNew ) { TodoView::complete( sorted()[row] ); return; } QTable::contentsMouseReleaseEvent( e ); } void TableView::contentsMouseMoveEvent( QMouseEvent* e ) { m_menuTimer->stop(); QTable::contentsMouseMoveEvent( e ); } void TableView::keyPressEvent( QKeyEvent* event) { if ( m_editorWidget.cellWidget() ) { // setCellContentFromEditor(m_editorWidget.cellRow(), m_editorWidget.cellCol() ); endEdit(m_editorWidget.cellRow(), m_editorWidget.cellCol(), true, true ); m_editorWidget.releaseCellWidget(); setFocus(); } if ( sorted().count() < 1 ) { QTable::keyPressEvent( event ); return; } int row = currentRow(); int col = currentColumn(); char key = ::toupper( event->ascii() ); /* let QTable also handle the d letter */ if ( key == 'D' ) { event->accept(); removeQuery( sorted().uidAt( row ) ); return; } switch( event->key() ) { case Qt::Key_F33: case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Space: if ( col == 0 ) { TodoView::complete(sorted()[row]); }else if ( col == 1 ) { QWidget* wid = beginEdit(row, col, FALSE ); m_editorWidget.setCellWidget( wid, row, col ); }else if ( col == 2 ) { showTodo( sorted().uidAt( currentRow() ) ); }else if ( col == 3 ) { TodoView::edit( sorted().uidAt(row) ); } event->accept(); break; default: QTable::keyPressEvent( event ); } } diff --git a/core/pim/todo/todomanager.cpp b/core/pim/todo/todomanager.cpp index c4b8fbc..7136f9a 100644 --- a/core/pim/todo/todomanager.cpp +++ b/core/pim/todo/todomanager.cpp @@ -1,130 +1,125 @@ /* =. This file is part of the OPIE Project .=l. Copyright (c) 2002 <> .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <opie2/odebug.h> #include <qpe/categoryselect.h> #include "todomanager.h" using namespace Todo; TodoManager::TodoManager( QObject *obj ) : QObject( obj ) { m_db = 0l; - QTime time; - time.start(); - int el = time.elapsed(); - owarn << "QTimer for loading " << el/1000 << oendl; } TodoManager::~TodoManager() { delete m_db; } OPimTodo TodoManager::event(int uid ) { return m_db->find( uid ); } void TodoManager::updateList() { - owarn << "update lists" << oendl; m_list = m_db->allRecords(); } OPimTodoAccess::List TodoManager::list() const{ return m_list; } OPimTodoAccess::List TodoManager::sorted( bool asc, int so, int f, int cat ) { return m_db->sorted( asc, so, f, cat ); } OPimTodoAccess::List::Iterator TodoManager::overDue() { - int filter = 2 | 1; + int filter = Opie::OPimTodoAccess::FilterCategory | Opie::OPimTodoAccess::OnlyOverDue; m_list = m_db->sorted(m_asc, m_sortOrder, filter, m_ca ); m_it = m_list.begin(); return m_it; } OPimTodoAccess::List::Iterator TodoManager::fromTo( const QDate& start, const QDate& end ) { m_list = m_db->effectiveToDos( start, end ); m_it = m_list.begin(); return m_it; } OPimTodoAccess::List::Iterator TodoManager::query( const OPimTodo& ev, int query ) { m_list = m_db->queryByExample( ev, query ); m_it = m_list.begin(); return m_it; } OPimTodoAccess* TodoManager::todoDB() { return m_db; } void TodoManager::add( const OPimTodo& ev ) { m_db->add( ev ); } void TodoManager::update( int, const SmallTodo& ) { } void TodoManager::update( int, const OPimTodo& ev) { m_db->replace( ev ); } bool TodoManager::remove( int uid ) { return m_db->remove( uid ); } void TodoManager::removeAll() { m_db->clear(); } void TodoManager::removeCompleted() { m_db->removeAllCompleted(); } void TodoManager::save() { m_db->save(); } bool TodoManager::saveAll() { return m_db->save(); } void TodoManager::reload() { m_db->reload(); } QStringList TodoManager::categories() { m_cat.load(categoryFileName() ); return m_cat.labels( "Todo List"); } /* * we rely on load beeing called from populateCategories */ int TodoManager::catId( const QString& cats ) { return m_cat.id( "Todo List", cats ); } void TodoManager::remove( const QArray<int>& ids) { for (uint i=0; i < ids.size(); i++ ) remove( ids[i] ); } bool TodoManager::isLoaded()const { return (m_db == 0 ); } void TodoManager::load() { if (!m_db) { m_db = new OPimTodoAccess(); m_db->load(); } } |