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( stopAllTimers() ),
00085            this, SLOT( stopAllTimers() ));
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     _manualSaveTimer->start( 10, true /*single-shot*/ );
00356 }
00357 
00358 Preferences* TaskView::preferences() { return _preferences; }
00359 
00360 QString TaskView::save()
00361 {
00362     // DF: this code created a new event for the running task(s),
00363     // at every call (very frequent with autosave) !!!
00364     // -> if one wants autosave to save the current event, then
00365     // Task needs to store the "current event" and we need to update
00366     // it before calling save.
00367 #if 0
00368   // Stop then start all timers so history entries are written.  This is
00369   // inefficient if more than one task running, but it is correct.  It is
00370   // inefficient because the iCalendar file is saved every time a task's
00371   // setRunning(false, ...) is called.  For a big ics file, this could be a
00372   // drag.  However, it does ensure that the data will be consistent.  And
00373   // if the most common use case is that one task is running most of the time,
00374   // it won't make any difference.
00375   for (unsigned int i = 0; i < activeTasks.count(); i++)
00376   {
00377     activeTasks.at(i)->setRunning(false, _storage);
00378     activeTasks.at(i)->setRunning(true, _storage);
00379   }
00380 
00381   // If there was an active task, the iCal file has already been saved.
00382   if (activeTasks.count() == 0)
00383 #endif
00384   {
00385     return _storage->save(this);
00386   }
00387 }
00388 
00389 void TaskView::startCurrentTimer()
00390 {
00391   startTimerFor( current_item() );
00392 }
00393 
00394 long TaskView::count()
00395 {
00396   long n = 0;
00397   for (Task* t = item_at_index(n); t; t=item_at_index(++n));
00398   return n;
00399 }
00400 
00401 void TaskView::startTimerFor(Task* task, QDateTime startTime )
00402 {
00403   if (task != 0 && activeTasks.findRef(task) == -1) {
00404     _idleTimeDetector->startIdleDetection();
00405     task->setRunning(true, _storage, startTime);
00406     activeTasks.append(task);
00407     emit updateButtons();
00408     if ( activeTasks.count() == 1 )
00409         emit timersActive();
00410 
00411     emit tasksChanged( activeTasks);
00412   }
00413 }
00414 
00415 void TaskView::clearActiveTasks()
00416 {
00417   activeTasks.clear();
00418 }
00419 
00420 void TaskView::stopAllTimers()
00421 {
00422   for ( unsigned int i = 0; i < activeTasks.count(); i++ )
00423     activeTasks.at(i)->setRunning(false, _storage);
00424 
00425   _idleTimeDetector->stopIdleDetection();
00426   activeTasks.clear();
00427   emit updateButtons();
00428   emit timersInactive();
00429   emit tasksChanged( activeTasks);
00430 }
00431 
00432 void TaskView::startNewSession()
00433 {
00434   QListViewItemIterator item( first_child());
00435   for ( ; item.current(); ++item ) {
00436     Task * task = (Task *) item.current();
00437     task->startNewSession();
00438   }
00439 }
00440 
00441 void TaskView::resetTimeForAllTasks()
00442 {
00443   QListViewItemIterator item( first_child());
00444   for ( ; item.current(); ++item ) {
00445     Task * task = (Task *) item.current();
00446     task->resetTimes();
00447   }
00448 }
00449 
00450 void TaskView::stopTimerFor(Task* task)
00451 {
00452   if ( task != 0 && activeTasks.findRef(task) != -1 ) {
00453     activeTasks.removeRef(task);
00454     task->setRunning(false, _storage);
00455     if ( activeTasks.count() == 0 ) {
00456       _idleTimeDetector->stopIdleDetection();
00457       emit timersInactive();
00458     }
00459     emit updateButtons();
00460   }
00461   emit tasksChanged( activeTasks);
00462 }
00463 
00464 void TaskView::stopCurrentTimer()
00465 {
00466   stopTimerFor( current_item());
00467 }
00468 
00469 void TaskView::minuteUpdate()
00470 {
00471   addTimeToActiveTasks(1, false);
00472 }
00473 
00474 void TaskView::addTimeToActiveTasks(int minutes, bool save_data)
00475 {
00476   for( unsigned int i = 0; i < activeTasks.count(); i++ )
00477     activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
00478 }
00479 
00480 void TaskView::newTask()
00481 {
00482   newTask(i18n("New Task"), 0);
00483 }
00484 
00485 void TaskView::newTask(QString caption, Task *parent)
00486 {
00487   EditTaskDialog *dialog = new EditTaskDialog(caption, false);
00488   long total, totalDiff, session, sessionDiff;
00489   DesktopList desktopList;
00490 
00491   int result = dialog->exec();
00492   if ( result == QDialog::Accepted ) {
00493     QString taskName = i18n( "Unnamed Task" );
00494     if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
00495 
00496     total = totalDiff = session = sessionDiff = 0;
00497     dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
00498 
00499     // If all available desktops are checked, disable auto tracking,
00500     // since it makes no sense to track for every desktop.
00501     if ( desktopList.size() == ( unsigned int ) _desktopTracker->desktopCount() )
00502       desktopList.clear();
00503 
00504     QString uid = addTask( taskName, total, session, desktopList, parent );
00505     if ( uid.isNull() )
00506     {
00507       KMessageBox::error( 0, i18n(
00508             "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/ " ) );
00509     }
00510 
00511     delete dialog;
00512   }
00513 }
00514 
00515 QString TaskView::addTask
00516 ( const QString& taskname, long total, long session, 
00517   const DesktopList& desktops, Task* parent )
00518 {
00519   Task *task;
00520 
00521   kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl;
00522 
00523   if ( parent ) task = new Task( taskname, total, session, desktops, parent );
00524   else          task = new Task( taskname, total, session, desktops, this );
00525 
00526   task->setUid( _storage->addTask( task, parent ) );
00527 
00528   if ( ! task->uid().isNull() )
00529   {
00530     _desktopTracker->registerForDesktops( task, desktops );
00531 
00532     setCurrentItem( task );
00533 
00534     setSelected( task, true );
00535 
00536     task->setPixmapProgress();
00537 
00538     save();
00539   }
00540   else
00541   {
00542     delete task;
00543   }
00544 
00545   return task->uid();
00546 }
00547 
00548 void TaskView::newSubTask()
00549 {
00550   Task* task = current_item();
00551   if(!task)
00552     return;
00553   newTask(i18n("New Sub Task"), task);
00554   task->setOpen(true);
00555   refresh();
00556 }
00557 
00558 void TaskView::editTask()
00559 {
00560   Task *task = current_item();
00561   if (!task)
00562     return;
00563 
00564   DesktopList desktopList = task->getDesktops();
00565   EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList);
00566   dialog->setTask( task->name(),
00567                    task->time(),
00568                    task->sessionTime() );
00569   int result = dialog->exec();
00570   if (result == QDialog::Accepted) {
00571     QString taskName = i18n("Unnamed Task");
00572     if (!dialog->taskName().isEmpty()) {
00573       taskName = dialog->taskName();
00574     }
00575     // setName only does something if the new name is different
00576     task->setName(taskName, _storage);
00577 
00578     // update session time as well if the time was changed
00579     long total, session, totalDiff, sessionDiff;
00580     total = totalDiff = session = sessionDiff = 0;
00581     DesktopList desktopList;
00582     dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00583 
00584     if( totalDiff != 0 || sessionDiff != 0)
00585       task->changeTimes( sessionDiff, totalDiff, _storage );
00586 
00587     // If all available desktops are checked, disable auto tracking,
00588     // since it makes no sense to track for every desktop.
00589     if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount())
00590       desktopList.clear();
00591 
00592     task->setDesktopList(desktopList);
00593 
00594     _desktopTracker->registerForDesktops( task, desktopList );
00595 
00596     emit updateButtons();
00597   }
00598   delete dialog;
00599 }
00600 
00601 //void TaskView::addCommentToTask()
00602 //{
00603 //  Task *task = current_item();
00604 //  if (!task)
00605 //    return;
00606 
00607 //  bool ok;
00608 //  QString comment = KLineEditDlg::getText(i18n("Comment"),
00609 //                       i18n("Log comment for task '%1':").arg(task->name()),
00610 //                       QString(), &ok, this);
00611 //  if ( ok )
00612 //    task->addComment( comment, _storage );
00613 //}
00614 
00615 void TaskView::reinstateTask(int completion)
00616 {
00617   Task* task = current_item();
00618   if (task == 0) {
00619     KMessageBox::information(0,i18n("No task selected."));
00620     return;
00621   }
00622 
00623   if (completion<0) completion=0;
00624   if (completion<100)
00625   {
00626     task->setPercentComplete(completion, _storage);
00627     task->setPixmapProgress();
00628     save();
00629     emit updateButtons();
00630   }
00631 }
00632 
00633 void TaskView::deleteTask(bool markingascomplete)
00634 {
00635   Task *task = current_item();
00636   if (task == 0) {
00637     KMessageBox::information(0,i18n("No task selected."));
00638     return;
00639   }
00640 
00641   int response = KMessageBox::Continue;
00642   if (!markingascomplete && _preferences->promptDelete()) {
00643     if (task->childCount() == 0) {
00644       response = KMessageBox::warningContinueCancel( 0,
00645           i18n( "Are you sure you want to delete "
00646           "the task named\n\"%1\" and its entire history?")
00647           .arg(task->name()),
00648           i18n( "Deleting Task"), KStdGuiItem::del());
00649     }
00650     else {
00651       response = KMessageBox::warningContinueCancel( 0,
00652           i18n( "Are you sure you want to delete the task named"
00653           "\n\"%1\" and its entire history?\n"
00654           "NOTE: all its subtasks and their history will also "
00655           "be deleted.").arg(task->name()),
00656           i18n( "Deleting Task"), KStdGuiItem::del());
00657     }
00658   }
00659 
00660   if (response == KMessageBox::Continue)
00661   {
00662     if (markingascomplete)
00663     {
00664       task->setPercentComplete(100, _storage);
00665       task->setPixmapProgress();
00666       save();
00667       emit updateButtons();
00668 
00669       // Have to remove after saving, as the save routine only affects tasks
00670       // that are in the view.  Otherwise, the new percent complete does not
00671       // get saved.   (No longer remove when marked as complete.)
00672       //task->removeFromView();
00673 
00674     }
00675     else
00676     {
00677       QString uid=task->uid();
00678       task->remove(activeTasks, _storage);
00679       task->removeFromView();
00680       if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed
00681       save();
00682     }
00683 
00684     // remove root decoration if there is no more children.
00685     refresh();
00686 
00687     // Stop idle detection if no more counters are running
00688     if (activeTasks.count() == 0) {
00689       _idleTimeDetector->stopIdleDetection();
00690       emit timersInactive();
00691     }
00692 
00693     emit tasksChanged( activeTasks );
00694   }
00695 }
00696 
00697 void TaskView::extractTime(int minutes)
00698 {
00699   addTimeToActiveTasks(-minutes);
00700 }
00701 
00702 void TaskView::autoSaveChanged(bool on)
00703 {
00704   if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
00705   else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
00706 }
00707 
00708 void TaskView::autoSavePeriodChanged(int /*minutes*/)
00709 {
00710   autoSaveChanged(_preferences->autoSave());
00711 }
00712 
00713 void TaskView::adaptColumns()
00714 {
00715   // to hide a column X we set it's width to 0
00716   // at that moment we'll remember the original column within
00717   // previousColumnWidths[X]
00718   //
00719   // When unhiding a previously hidden column
00720   // (previousColumnWidths[X] != HIDDEN_COLUMN !)
00721   // we restore it's width from the saved value and set
00722   // previousColumnWidths[X] to HIDDEN_COLUMN
00723 
00724   for( int x=1; x <= 4; x++) {
00725     // the column was invisible before and were switching it on now
00726     if(   _preferences->displayColumn(x-1)
00727        && previousColumnWidths[x-1] != HIDDEN_COLUMN )
00728     {
00729       setColumnWidth( x, previousColumnWidths[x-1] );
00730       previousColumnWidths[x-1] = HIDDEN_COLUMN;
00731       setColumnWidthMode( x, QListView::Maximum );
00732     }
00733     // the column was visible before and were switching it off now
00734     else
00735     if( ! _preferences->displayColumn(x-1)
00736        && previousColumnWidths[x-1] == HIDDEN_COLUMN )
00737     {
00738       setColumnWidthMode( x, QListView::Manual ); // we don't want update()
00739                                                   // to resize/unhide the col
00740       previousColumnWidths[x-1] = columnWidth( x );
00741       setColumnWidth( x, 0 );
00742     }
00743   }
00744 }
00745 
00746 void TaskView::deletingTask(Task* deletedTask)
00747 {
00748   DesktopList desktopList;
00749 
00750   _desktopTracker->registerForDesktops( deletedTask, desktopList );
00751   activeTasks.removeRef( deletedTask );
00752 
00753   emit tasksChanged( activeTasks);
00754 }
00755 
00756 void TaskView::iCalFileChanged(QString file)
00757 {
00758   kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl;
00759   stopAllTimers();
00760   _storage->save(this);
00761   load();
00762 }
00763 
00764 QValueList<HistoryEvent> TaskView::getHistory(const QDate& from,
00765     const QDate& to) const
00766 {
00767   return _storage->getHistory(from, to);
00768 }
00769 
00770 void TaskView::markTaskAsComplete()
00771 {
00772   if (current_item())
00773     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00774       << current_item()->uid() << endl;
00775   else
00776     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00777 
00778   bool markingascomplete = true;
00779   deleteTask(markingascomplete);
00780 }
00781 
00782 void TaskView::markTaskAsIncomplete()
00783 {
00784   if (current_item())
00785     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00786       << current_item()->uid() << endl;
00787   else
00788     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00789 
00790   reinstateTask(50); // if it has been reopened, assume half-done
00791 }
00792 
00793 
00794 void TaskView::clipTotals()
00795 {
00796   TimeKard t;
00797   if (current_item() && current_item()->isRoot())
00798   {
00799     int response = KMessageBox::questionYesNo( 0,
00800         i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"),
00801         i18n("Copy Totals to Clipboard"),
00802         i18n("Copy This Task"), i18n("Copy All Tasks") );
00803     if (response == KMessageBox::Yes) // this task only
00804     {
00805       KApplication::clipboard()->setText(t.totalsAsText(this));
00806     }
00807     else // only task
00808     {
00809       KApplication::clipboard()->setText(t.totalsAsText(this, false));
00810     }
00811   }
00812   else
00813   {
00814     KApplication::clipboard()->setText(t.totalsAsText(this));
00815   }
00816 }
00817 
00818 void TaskView::clipHistory()
00819 {
00820   PrintDialog dialog;
00821   if (dialog.exec()== QDialog::Accepted)
00822   {
00823     TimeKard t;
00824     KApplication::clipboard()->
00825       setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
00826   }
00827 }
00828 
00829 #include "taskview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys