karm

taskview.cpp

00001 #include <qclipboard.h>
00002 #include <qfile.h>
00003 #include <qlayout.h>
00004 #include <qlistbox.h>
00005 #include <qlistview.h>
00006 #include <qptrlist.h>
00007 #include <qptrstack.h>
00008 #include <qstring.h>
00009 #include <qtextstream.h>
00010 #include <qtimer.h>
00011 #include <qxml.h>
00012 
00013 #include "kapplication.h"       // kapp
00014 #include <kconfig.h>
00015 #include <kdebug.h>
00016 #include <kfiledialog.h>
00017 #include <klocale.h>            // i18n
00018 #include <kmessagebox.h>
00019 #include <kurlrequester.h>
00020 
00021 #include "csvexportdialog.h"
00022 #include "desktoptracker.h"
00023 #include "edittaskdialog.h"
00024 #include "idletimedetector.h"
00025 #include "karmstorage.h"
00026 #include "plannerparser.h"
00027 #include "preferences.h"
00028 #include "printdialog.h"
00029 #include "reportcriteria.h"
00030 #include "task.h"
00031 #include "taskview.h"
00032 #include "timekard.h"
00033 #include "taskviewwhatsthis.h"
00034 
00035 #define T_LINESIZE 1023
00036 #define HIDDEN_COLUMN -10
00037 
00038 class DesktopTracker;
00039 
00040 TaskView::TaskView(QWidget *parent, const char *name, const QString &icsfile ):KListView(parent,name)
00041 {
00042   _preferences = Preferences::instance( icsfile );
00043   _storage = KarmStorage::instance();
00044 
00045   connect( this, SIGNAL( expanded( QListViewItem * ) ),
00046            this, SLOT( itemStateChanged( QListViewItem * ) ) );
00047   connect( this, SIGNAL( collapsed( QListViewItem * ) ),
00048            this, SLOT( itemStateChanged( QListViewItem * ) ) );
00049 
00050   // setup default values
00051   previousColumnWidths[0] = previousColumnWidths[1]
00052   = previousColumnWidths[2] = previousColumnWidths[3] = HIDDEN_COLUMN;
00053 
00054   addColumn( i18n("Task Name") );
00055   addColumn( i18n("Session Time") );
00056   addColumn( i18n("Time") );
00057   addColumn( i18n("Total Session Time") );
00058   addColumn( i18n("Total Time") );
00059   setColumnAlignment( 1, Qt::AlignRight );
00060   setColumnAlignment( 2, Qt::AlignRight );
00061   setColumnAlignment( 3, Qt::AlignRight );
00062   setColumnAlignment( 4, Qt::AlignRight );
00063   adaptColumns();
00064   setAllColumnsShowFocus( true );
00065 
00066   // set up the minuteTimer
00067   _minuteTimer = new QTimer(this);
00068   connect( _minuteTimer, SIGNAL( timeout() ), this, SLOT( minuteUpdate() ));
00069   _minuteTimer->start(1000 * secsPerMinute);
00070 
00071   // React when user changes iCalFile
00072   connect(_preferences, SIGNAL(iCalFile(QString)),
00073       this, SLOT(iCalFileChanged(QString)));
00074 
00075   // resize columns when config is changed
00076   connect(_preferences, SIGNAL( setupChanged() ), this,SLOT( adaptColumns() ));
00077 
00078   _minuteTimer->start(1000 * secsPerMinute);
00079 
00080   // Set up the idle detection.
00081   _idleTimeDetector = new IdleTimeDetector( _preferences->idlenessTimeout() );
00082   connect( _idleTimeDetector, SIGNAL( extractTime(int) ),
00083            this, SLOT( extractTime(int) ));
00084   connect( _idleTimeDetector, SIGNAL( stopAllTimersAt(QDateTime) ),
00085            this, SLOT( stopAllTimersAt(QDateTime) ));
00086   connect( _preferences, SIGNAL( idlenessTimeout(int) ),
00087            _idleTimeDetector, SLOT( setMaxIdle(int) ));
00088   connect( _preferences, SIGNAL( detectIdleness(bool) ),
00089            _idleTimeDetector, SLOT( toggleOverAllIdleDetection(bool) ));
00090   if (!_idleTimeDetector->isIdleDetectionPossible())
00091     _preferences->disableIdleDetection();
00092 
00093   // Setup auto save timer
00094   _autoSaveTimer = new QTimer(this);
00095   connect( _preferences, SIGNAL( autoSave(bool) ),
00096            this, SLOT( autoSaveChanged(bool) ));
00097   connect( _preferences, SIGNAL( autoSavePeriod(int) ),
00098            this, SLOT( autoSavePeriodChanged(int) ));
00099   connect( _autoSaveTimer, SIGNAL( timeout() ), this, SLOT( save() ));
00100 
00101   // Setup manual save timer (to save changes a little while after they happen)
00102   _manualSaveTimer = new QTimer(this);
00103   connect( _manualSaveTimer, SIGNAL( timeout() ), this, SLOT( save() ));
00104 
00105   // Connect desktop tracker events to task starting/stopping
00106   _desktopTracker = new DesktopTracker();
00107   connect( _desktopTracker, SIGNAL( reachedtActiveDesktop( Task* ) ),
00108            this, SLOT( startTimerFor(Task*) ));
00109   connect( _desktopTracker, SIGNAL( leftActiveDesktop( Task* ) ),
00110            this, SLOT( stopTimerFor(Task*) ));
00111   new TaskViewWhatsThis( this );
00112 }
00113 
00114 KarmStorage* TaskView::storage()
00115 {
00116   return _storage;
00117 }
00118 
00119 void TaskView::contentsMousePressEvent ( QMouseEvent * e )
00120 {
00121   kdDebug(5970) << "entering contentsMousePressEvent" << endl;
00122   KListView::contentsMousePressEvent(e);
00123   Task* task = current_item();
00124   // This checks that there has been a click onto an item,  
00125   // not into an empty part of the KListView.
00126   if ( task != 0 &&  // zero can happen if there is no task
00127         e->pos().y() >= current_item()->itemPos() &&
00128         e->pos().y() < current_item()->itemPos()+current_item()->height() )
00129   { 
00130     // see if the click was on the completed icon
00131     int leftborder = treeStepSize() * ( task->depth() + ( rootIsDecorated() ? 1 : 0)) + itemMargin();
00132     if ((leftborder < e->x()) && (e->x() < 19 + leftborder ))
00133     {
00134       if ( task->isComplete() ) task->setPercentComplete( 0, _storage );
00135       else task->setPercentComplete( 100, _storage );
00136     }
00137     emit updateButtons();
00138   }
00139 }
00140 
00141 void TaskView::contentsMouseDoubleClickEvent ( QMouseEvent * e )
00142 // if the user double-clicks onto a tasks, he says "I am now working exclusively
00143 // on that task". That means, on a doubleclick, we check if it occurs on an item
00144 // not in the blank space, if yes, stop all other tasks and start the new timer.
00145 {
00146   kdDebug(5970) << "entering contentsMouseDoubleClickEvent" << endl;
00147   KListView::contentsMouseDoubleClickEvent(e);
00148   
00149   Task *task = current_item();
00150 
00151   if ( task != 0 )  // current_item() exists
00152   {
00153     if ( e->pos().y() >= task->itemPos() &&  // doubleclick was onto current_item()
00154           e->pos().y() < task->itemPos()+task->height() )
00155     {
00156       if ( activeTasks.findRef(task) == -1 )  // task is active
00157       {
00158         stopAllTimers();
00159         startCurrentTimer();
00160       }
00161       else stopCurrentTimer();
00162     }
00163   }
00164 }
00165 
00166 TaskView::~TaskView()
00167 {
00168   _preferences->save();
00169 }
00170 
00171 Task* TaskView::first_child() const
00172 {
00173   return static_cast<Task*>(firstChild());
00174 }
00175 
00176 Task* TaskView::current_item() const
00177 {
00178   return static_cast<Task*>(currentItem());
00179 }
00180 
00181 Task* TaskView::item_at_index(int i)
00182 {
00183   return static_cast<Task*>(itemAtIndex(i));
00184 }
00185 
00186 void TaskView::load( QString fileName )
00187 {
00188   // if the program is used as an embedded plugin for konqueror, there may be a need
00189   // to load from a file without touching the preferences.
00190   _isloading = true;
00191   QString err = _storage->load(this, _preferences, fileName);
00192 
00193   if (!err.isEmpty())
00194   {
00195     KMessageBox::error(this, err);
00196     _isloading = false;
00197     return;
00198   }
00199 
00200   // Register tasks with desktop tracker
00201   int i = 0;
00202   for ( Task* t = item_at_index(i); t; t = item_at_index(++i) )
00203     _desktopTracker->registerForDesktops( t, t->getDesktops() );
00204 
00205   restoreItemState( first_child() );
00206 
00207   setSelected(first_child(), true);
00208   setCurrentItem(first_child());
00209   _desktopTracker->startTracking();
00210   _isloading = false;
00211   refresh();
00212 }
00213 
00214 void TaskView::restoreItemState( QListViewItem *item )
00215 {
00216   while( item ) 
00217   {
00218     Task *t = (Task *)item;
00219     t->setOpen( _preferences->readBoolEntry( t->uid() ) );
00220     if( item->childCount() > 0 ) restoreItemState( item->firstChild() );
00221     item = item->nextSibling();
00222   }
00223 }
00224 
00225 void TaskView::itemStateChanged( QListViewItem *item )
00226 {
00227   if ( !item || _isloading ) return;
00228   Task *t = (Task *)item;
00229   kdDebug(5970) << "TaskView::itemStateChanged()" 
00230     << " uid=" << t->uid() << " state=" << t->isOpen()
00231     << endl;
00232   if( _preferences ) _preferences->writeEntry( t->uid(), t->isOpen() );
00233 }
00234 
00235 void TaskView::closeStorage() { _storage->closeStorage( this ); }
00236 
00237 void TaskView::iCalFileModified(ResourceCalendar *rc)
00238 {
00239   kdDebug(5970) << "entering iCalFileModified" << endl;
00240   kdDebug(5970) << rc->infoText() << endl;
00241   rc->dump();
00242   _storage->buildTaskView(rc,this);
00243   kdDebug(5970) << "exiting iCalFileModified" << endl;
00244 }
00245 
00246 void TaskView::refresh()
00247 {
00248   kdDebug(5970) << "entering TaskView::refresh()" << endl;
00249   this->setRootIsDecorated(true);
00250   int i = 0;
00251   for ( Task* t = item_at_index(i); t; t = item_at_index(++i) )
00252   {
00253     t->setPixmapProgress();
00254   }
00255   
00256   // remove root decoration if there is no more children.
00257   bool anyChilds = false;
00258   for(Task* child = first_child();
00259             child;
00260             child = child->nextSibling()) {
00261     if (child->childCount() != 0) {
00262       anyChilds = true;
00263       break;
00264     }
00265   }
00266   if (!anyChilds) {
00267     setRootIsDecorated(false);
00268   }
00269   emit updateButtons();
00270   kdDebug(5970) << "exiting TaskView::refresh()" << endl;
00271 }
00272     
00273 void TaskView::loadFromFlatFile()
00274 {
00275   kdDebug(5970) << "TaskView::loadFromFlatFile()" << endl;
00276 
00277   //KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
00278 
00279   QString fileName(KFileDialog::getOpenFileName(QString::null, QString::null,
00280         0));
00281   if (!fileName.isEmpty()) {
00282     QString err = _storage->loadFromFlatFile(this, fileName);
00283     if (!err.isEmpty())
00284     {
00285       KMessageBox::error(this, err);
00286       return;
00287     }
00288     // Register tasks with desktop tracker
00289     int task_idx = 0;
00290     Task* task = item_at_index(task_idx++);
00291     while (task)
00292     {
00293       // item_at_index returns 0 where no more items.
00294       _desktopTracker->registerForDesktops( task, task->getDesktops() );
00295       task = item_at_index(task_idx++);
00296     }
00297 
00298     setSelected(first_child(), true);
00299     setCurrentItem(first_child());
00300 
00301     _desktopTracker->startTracking();
00302   }
00303 }
00304 
00305 QString TaskView::importPlanner(QString fileName)
00306 {
00307   kdDebug(5970) << "entering importPlanner" << endl;
00308   PlannerParser* handler=new PlannerParser(this);
00309   if (fileName.isEmpty()) fileName=KFileDialog::getOpenFileName(QString::null, QString::null, 0);
00310   QFile xmlFile( fileName );
00311   QXmlInputSource source( xmlFile );
00312   QXmlSimpleReader reader;
00313   reader.setContentHandler( handler );
00314   reader.parse( source );
00315   refresh();
00316   return "";
00317 }
00318 
00319 QString TaskView::report( const ReportCriteria& rc )
00320 {
00321   return _storage->report( this, rc );
00322 }
00323 
00324 void TaskView::exportcsvFile()
00325 {
00326   kdDebug(5970) << "TaskView::exportcsvFile()" << endl;
00327 
00328   CSVExportDialog dialog( ReportCriteria::CSVTotalsExport, this );
00329   if ( current_item() && current_item()->isRoot() )
00330     dialog.enableTasksToExportQuestion();
00331   dialog.urlExportTo->KURLRequester::setMode(KFile::File);
00332   if ( dialog.exec() ) {
00333     QString err = _storage->report( this, dialog.reportCriteria() );
00334     if ( !err.isEmpty() ) KMessageBox::error( this, i18n(err.ascii()) );
00335   }
00336 }
00337 
00338 QString TaskView::exportcsvHistory()
00339 {
00340   kdDebug(5970) << "TaskView::exportcsvHistory()" << endl;
00341   QString err;
00342   
00343   CSVExportDialog dialog( ReportCriteria::CSVHistoryExport, this );
00344   if ( current_item() && current_item()->isRoot() )
00345     dialog.enableTasksToExportQuestion();
00346   dialog.urlExportTo->KURLRequester::setMode(KFile::File);
00347   if ( dialog.exec() ) {
00348     err = _storage->report( this, dialog.reportCriteria() );
00349   }
00350   return err;
00351 }
00352 
00353 void TaskView::scheduleSave()
00354 {
00355   kdDebug(5970) << "Entering TaskView::scheduleSave" << endl;
00356   // save changes a little while after they happen
00357   _manualSaveTimer->start( 10, true /*single-shot*/ );
00358 }
00359 
00360 Preferences* TaskView::preferences() { return _preferences; }
00361 
00362 QString TaskView::save()
00363 // This saves the not-running tasks.
00364 {
00365   kdDebug(5970) << "Entering TaskView::save" << endl;
00366   QString err = _storage->save(this);
00367   emit(setStatusBar(err));
00368   return err;
00369 }
00370 
00371 void TaskView::startCurrentTimer()
00372 {
00373   startTimerFor( current_item() );
00374 }
00375 
00376 long TaskView::count()
00377 {
00378   long n = 0;
00379   for (Task* t = item_at_index(n); t; t=item_at_index(++n));
00380   return n;
00381 }
00382 
00383 void TaskView::startTimerFor(Task* task, QDateTime startTime )
00384 {
00385   if (task != 0 && activeTasks.findRef(task) == -1) {
00386     _idleTimeDetector->startIdleDetection();
00387     task->setRunning(true, _storage, startTime);
00388     activeTasks.append(task);
00389     emit updateButtons();
00390     if ( activeTasks.count() == 1 )
00391         emit timersActive();
00392 
00393     emit tasksChanged( activeTasks);
00394   }
00395 }
00396 
00397 void TaskView::clearActiveTasks()
00398 {
00399   activeTasks.clear();
00400 }
00401 
00402 void TaskView::stopAllTimers()
00403 {
00404   kdDebug(5970) << "Entering TaskView::stopAllTimers()" << endl;
00405   for ( unsigned int i = 0; i < activeTasks.count(); i++ )
00406     activeTasks.at(i)->setRunning(false, _storage);
00407 
00408   _idleTimeDetector->stopIdleDetection();
00409   activeTasks.clear();
00410   emit updateButtons();
00411   emit timersInactive();
00412   emit tasksChanged( activeTasks );
00413 }
00414 
00415 void TaskView::stopAllTimersAt(QDateTime qdt)
00416 // stops all timers for the time qdt. This makes sense, if the idletimedetector detected
00417 // the last work has been done 50 minutes ago.
00418 {
00419   kdDebug(5970) << "Entering TaskView::stopAllTimersAt" << endl;
00420   for ( unsigned int i = 0; i < activeTasks.count(); i++ )
00421   {
00422     activeTasks.at(i)->setRunning(false, _storage, qdt, qdt);
00423     kdDebug() << activeTasks.at(i)->name() << endl;
00424   }
00425 
00426   _idleTimeDetector->stopIdleDetection();
00427   activeTasks.clear();
00428   emit updateButtons();
00429   emit timersInactive();
00430   emit tasksChanged( activeTasks );
00431 }
00432 
00433 void TaskView::startNewSession()
00434 {
00435   QListViewItemIterator item( first_child());
00436   for ( ; item.current(); ++item ) {
00437     Task * task = (Task *) item.current();
00438     task->startNewSession();
00439   }
00440 }
00441 
00442 void TaskView::resetTimeForAllTasks()
00443 {
00444   QListViewItemIterator item( first_child());
00445   for ( ; item.current(); ++item ) {
00446     Task * task = (Task *) item.current();
00447     task->resetTimes();
00448   }
00449 }
00450 
00451 void TaskView::stopTimerFor(Task* task)
00452 {
00453   kdDebug(5970) << "Entering stopTimerFor. task = " << task->name() << endl;
00454   if ( task != 0 && activeTasks.findRef(task) != -1 ) {
00455     activeTasks.removeRef(task);
00456     task->setRunning(false, _storage);
00457     if ( activeTasks.count() == 0 ) {
00458       _idleTimeDetector->stopIdleDetection();
00459       emit timersInactive();
00460     }
00461     emit updateButtons();
00462   }
00463   emit tasksChanged( activeTasks);
00464 }
00465 
00466 void TaskView::stopCurrentTimer()
00467 {
00468   stopTimerFor( current_item());
00469 }
00470 
00471 void TaskView::minuteUpdate()
00472 {
00473   addTimeToActiveTasks(1, false);
00474 }
00475 
00476 void TaskView::addTimeToActiveTasks(int minutes, bool save_data)
00477 {
00478   for( unsigned int i = 0; i < activeTasks.count(); i++ )
00479     activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
00480 }
00481 
00482 void TaskView::newTask()
00483 {
00484   newTask(i18n("New Task"), 0);
00485 }
00486 
00487 void TaskView::newTask(QString caption, Task *parent)
00488 {
00489   EditTaskDialog *dialog = new EditTaskDialog(caption, false);
00490   long total, totalDiff, session, sessionDiff;
00491   DesktopList desktopList;
00492 
00493   int result = dialog->exec();
00494   if ( result == QDialog::Accepted ) {
00495     QString taskName = i18n( "Unnamed Task" );
00496     if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
00497 
00498     total = totalDiff = session = sessionDiff = 0;
00499     dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
00500 
00501     // If all available desktops are checked, disable auto tracking,
00502     // since it makes no sense to track for every desktop.
00503     if ( desktopList.size() == ( unsigned int ) _desktopTracker->desktopCount() )
00504       desktopList.clear();
00505 
00506     QString uid = addTask( taskName, total, session, desktopList, parent );
00507     if ( uid.isNull() )
00508     {
00509       KMessageBox::error( 0, i18n(
00510             "Error storing new task. Your changes were not saved. Make sure you can edit your iCalendar file. Also quit all applications using this file and remove any lock file related to its name from ~/.kde/share/apps/kabc/lock/ " ) );
00511     }
00512 
00513     delete dialog;
00514   }
00515 }
00516 
00517 QString TaskView::addTask
00518 ( const QString& taskname, long total, long session, 
00519   const DesktopList& desktops, Task* parent )
00520 {
00521   Task *task;
00522   kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl;
00523 
00524   if ( parent ) task = new Task( taskname, total, session, desktops, parent );
00525   else          task = new Task( taskname, total, session, desktops, this );
00526 
00527   task->setUid( _storage->addTask( task, parent ) );
00528   QString taskuid=task->uid();
00529   if ( ! taskuid.isNull() )
00530   {
00531     _desktopTracker->registerForDesktops( task, desktops );
00532     setCurrentItem( task );
00533     setSelected( task, true );
00534     task->setPixmapProgress();
00535     save();
00536   }
00537   else
00538   {
00539     delete task;
00540   }
00541   return taskuid;
00542 }
00543 
00544 void TaskView::newSubTask()
00545 {
00546   Task* task = current_item();
00547   if(!task)
00548     return;
00549   newTask(i18n("New Sub Task"), task);
00550   task->setOpen(true);
00551   refresh();
00552 }
00553 
00554 void TaskView::editTask()
00555 {
00556   Task *task = current_item();
00557   if (!task)
00558     return;
00559 
00560   DesktopList desktopList = task->getDesktops();
00561   EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList);
00562   dialog->setTask( task->name(),
00563                    task->time(),
00564                    task->sessionTime() );
00565   int result = dialog->exec();
00566   if (result == QDialog::Accepted) {
00567     QString taskName = i18n("Unnamed Task");
00568     if (!dialog->taskName().isEmpty()) {
00569       taskName = dialog->taskName();
00570     }
00571     // setName only does something if the new name is different
00572     task->setName(taskName, _storage);
00573 
00574     // update session time as well if the time was changed
00575     long total, session, totalDiff, sessionDiff;
00576     total = totalDiff = session = sessionDiff = 0;
00577     DesktopList desktopList;
00578     dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00579 
00580     if( totalDiff != 0 || sessionDiff != 0)
00581       task->changeTimes( sessionDiff, totalDiff, _storage );
00582 
00583     // If all available desktops are checked, disable auto tracking,
00584     // since it makes no sense to track for every desktop.
00585     if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount())
00586       desktopList.clear();
00587 
00588     task->setDesktopList(desktopList);
00589 
00590     _desktopTracker->registerForDesktops( task, desktopList );
00591 
00592     emit updateButtons();
00593   }
00594   delete dialog;
00595 }
00596 
00597 //void TaskView::addCommentToTask()
00598 //{
00599 //  Task *task = current_item();
00600 //  if (!task)
00601 //    return;
00602 
00603 //  bool ok;
00604 //  QString comment = KLineEditDlg::getText(i18n("Comment"),
00605 //                       i18n("Log comment for task '%1':").arg(task->name()),
00606 //                       QString(), &ok, this);
00607 //  if ( ok )
00608 //    task->addComment( comment, _storage );
00609 //}
00610 
00611 void TaskView::reinstateTask(int completion)
00612 {
00613   Task* task = current_item();
00614   if (task == 0) {
00615     KMessageBox::information(0,i18n("No task selected."));
00616     return;
00617   }
00618 
00619   if (completion<0) completion=0;
00620   if (completion<100)
00621   {
00622     task->setPercentComplete(completion, _storage);
00623     task->setPixmapProgress();
00624     save();
00625     emit updateButtons();
00626   }
00627 }
00628 
00629 void TaskView::deleteTask(bool markingascomplete)
00630 {
00631   Task *task = current_item();
00632   if (task == 0) {
00633     KMessageBox::information(0,i18n("No task selected."));
00634     return;
00635   }
00636 
00637   int response = KMessageBox::Continue;
00638   if (!markingascomplete && _preferences->promptDelete()) {
00639     if (task->childCount() == 0) {
00640       response = KMessageBox::warningContinueCancel( 0,
00641           i18n( "Are you sure you want to delete "
00642           "the task named\n\"%1\" and its entire history?")
00643           .arg(task->name()),
00644           i18n( "Deleting Task"), KStdGuiItem::del());
00645     }
00646     else {
00647       response = KMessageBox::warningContinueCancel( 0,
00648           i18n( "Are you sure you want to delete the task named"
00649           "\n\"%1\" and its entire history?\n"
00650           "NOTE: all its subtasks and their history will also "
00651           "be deleted.").arg(task->name()),
00652           i18n( "Deleting Task"), KStdGuiItem::del());
00653     }
00654   }
00655 
00656   if (response == KMessageBox::Continue)
00657   {
00658     if (markingascomplete)
00659     {
00660       task->setPercentComplete(100, _storage);
00661       task->setPixmapProgress();
00662       save();
00663       emit updateButtons();
00664 
00665       // Have to remove after saving, as the save routine only affects tasks
00666       // that are in the view.  Otherwise, the new percent complete does not
00667       // get saved.   (No longer remove when marked as complete.)
00668       //task->removeFromView();
00669 
00670     }
00671     else
00672     {
00673       QString uid=task->uid();
00674       task->remove(activeTasks, _storage);
00675       task->removeFromView();
00676       if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed
00677       save();
00678     }
00679 
00680     // remove root decoration if there is no more children.
00681     refresh();
00682 
00683     // Stop idle detection if no more counters are running
00684     if (activeTasks.count() == 0) {
00685       _idleTimeDetector->stopIdleDetection();
00686       emit timersInactive();
00687     }
00688 
00689     emit tasksChanged( activeTasks );
00690   }
00691 }
00692 
00693 void TaskView::extractTime(int minutes)
00694 {
00695   kdDebug(5970) << "Entering extractTime" << endl;
00696   addTimeToActiveTasks(-minutes);
00697 }
00698 
00699 void TaskView::autoSaveChanged(bool on)
00700 {
00701   if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
00702   else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
00703 }
00704 
00705 void TaskView::autoSavePeriodChanged(int /*minutes*/)
00706 {
00707   autoSaveChanged(_preferences->autoSave());
00708 }
00709 
00710 void TaskView::adaptColumns()
00711 {
00712   // to hide a column X we set it's width to 0
00713   // at that moment we'll remember the original column within
00714   // previousColumnWidths[X]
00715   //
00716   // When unhiding a previously hidden column
00717   // (previousColumnWidths[X] != HIDDEN_COLUMN !)
00718   // we restore it's width from the saved value and set
00719   // previousColumnWidths[X] to HIDDEN_COLUMN
00720 
00721   for( int x=1; x <= 4; x++) {
00722     // the column was invisible before and were switching it on now
00723     if(   _preferences->displayColumn(x-1)
00724        && previousColumnWidths[x-1] != HIDDEN_COLUMN )
00725     {
00726       setColumnWidth( x, previousColumnWidths[x-1] );
00727       previousColumnWidths[x-1] = HIDDEN_COLUMN;
00728       setColumnWidthMode( x, QListView::Maximum );
00729     }
00730     // the column was visible before and were switching it off now
00731     else
00732     if( ! _preferences->displayColumn(x-1)
00733        && previousColumnWidths[x-1] == HIDDEN_COLUMN )
00734     {
00735       setColumnWidthMode( x, QListView::Manual ); // we don't want update()
00736                                                   // to resize/unhide the col
00737       previousColumnWidths[x-1] = columnWidth( x );
00738       setColumnWidth( x, 0 );
00739     }
00740   }
00741 }
00742 
00743 void TaskView::deletingTask(Task* deletedTask)
00744 {
00745   DesktopList desktopList;
00746 
00747   _desktopTracker->registerForDesktops( deletedTask, desktopList );
00748   activeTasks.removeRef( deletedTask );
00749 
00750   emit tasksChanged( activeTasks);
00751 }
00752 
00753 void TaskView::iCalFileChanged(QString file)
00754 // User might have picked a new file in the preferences dialog.
00755 // This is not iCalFileModified.
00756 {
00757   kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl;
00758   if (_storage->icalfile() != file)
00759   {
00760     stopAllTimers();
00761     _storage->save(this);
00762     load();
00763   }
00764 }
00765 
00766 QValueList<HistoryEvent> TaskView::getHistory(const QDate& from,
00767     const QDate& to) const
00768 {
00769   return _storage->getHistory(from, to);
00770 }
00771 
00772 void TaskView::markTaskAsComplete()
00773 {
00774   if (current_item())
00775     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00776       << current_item()->uid() << endl;
00777   else
00778     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00779 
00780   bool markingascomplete = true;
00781   deleteTask(markingascomplete);
00782 }
00783 
00784 void TaskView::markTaskAsIncomplete()
00785 {
00786   if (current_item())
00787     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00788       << current_item()->uid() << endl;
00789   else
00790     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00791 
00792   reinstateTask(50); // if it has been reopened, assume half-done
00793 }
00794 
00795 
00796 void TaskView::clipTotals()
00797 {
00798   TimeKard t;
00799   if (current_item() && current_item()->isRoot())
00800   {
00801     int response = KMessageBox::questionYesNo( 0,
00802         i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"),
00803         i18n("Copy Totals to Clipboard"),
00804         i18n("Copy This Task"), i18n("Copy All Tasks") );
00805     if (response == KMessageBox::Yes) // This task only
00806     {
00807       KApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
00808     }
00809     else // All tasks
00810     {
00811       KApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::TotalTime));
00812     }
00813   }
00814   else
00815   {
00816     KApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
00817   }
00818 }
00819 
00820 void TaskView::clipSession()
00821 {
00822   TimeKard t;
00823   if (current_item() && current_item()->isRoot())
00824   {
00825     int response = KMessageBox::questionYesNo( 0,
00826         i18n("Copy session time for just this task and its subtasks, or copy session time for all tasks?"),
00827         i18n("Copy Session Time to Clipboard"),
00828         i18n("Copy This Task"), i18n("Copy All Tasks") );
00829     if (response == KMessageBox::Yes) // this task only
00830     {
00831       KApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
00832     }
00833     else // only task
00834     {
00835       KApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::SessionTime));
00836     }
00837   }
00838   else
00839   {
00840     KApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
00841   }
00842 }
00843 
00844 void TaskView::clipHistory()
00845 {
00846   PrintDialog dialog;
00847   if (dialog.exec()== QDialog::Accepted)
00848   {
00849     TimeKard t;
00850     KApplication::clipboard()->
00851       setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
00852   }
00853 }
00854 
00855 #include "taskview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys