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   kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl;
00521 
00522   if ( parent ) task = new Task( taskname, total, session, desktops, parent );
00523   else          task = new Task( taskname, total, session, desktops, this );
00524 
00525   task->setUid( _storage->addTask( task, parent ) );
00526   QString taskuid=task->uid();
00527   if ( ! taskuid.isNull() )
00528   {
00529     _desktopTracker->registerForDesktops( task, desktops );
00530     setCurrentItem( task );
00531     setSelected( task, true );
00532     task->setPixmapProgress();
00533     save();
00534   }
00535   else
00536   {
00537     delete task;
00538   }
00539   return taskuid;
00540 }
00541 
00542 void TaskView::newSubTask()
00543 {
00544   Task* task = current_item();
00545   if(!task)
00546     return;
00547   newTask(i18n("New Sub Task"), task);
00548   task->setOpen(true);
00549   refresh();
00550 }
00551 
00552 void TaskView::editTask()
00553 {
00554   Task *task = current_item();
00555   if (!task)
00556     return;
00557 
00558   DesktopList desktopList = task->getDesktops();
00559   EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList);
00560   dialog->setTask( task->name(),
00561                    task->time(),
00562                    task->sessionTime() );
00563   int result = dialog->exec();
00564   if (result == QDialog::Accepted) {
00565     QString taskName = i18n("Unnamed Task");
00566     if (!dialog->taskName().isEmpty()) {
00567       taskName = dialog->taskName();
00568     }
00569     // setName only does something if the new name is different
00570     task->setName(taskName, _storage);
00571 
00572     // update session time as well if the time was changed
00573     long total, session, totalDiff, sessionDiff;
00574     total = totalDiff = session = sessionDiff = 0;
00575     DesktopList desktopList;
00576     dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00577 
00578     if( totalDiff != 0 || sessionDiff != 0)
00579       task->changeTimes( sessionDiff, totalDiff, _storage );
00580 
00581     // If all available desktops are checked, disable auto tracking,
00582     // since it makes no sense to track for every desktop.
00583     if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount())
00584       desktopList.clear();
00585 
00586     task->setDesktopList(desktopList);
00587 
00588     _desktopTracker->registerForDesktops( task, desktopList );
00589 
00590     emit updateButtons();
00591   }
00592   delete dialog;
00593 }
00594 
00595 //void TaskView::addCommentToTask()
00596 //{
00597 //  Task *task = current_item();
00598 //  if (!task)
00599 //    return;
00600 
00601 //  bool ok;
00602 //  QString comment = KLineEditDlg::getText(i18n("Comment"),
00603 //                       i18n("Log comment for task '%1':").arg(task->name()),
00604 //                       QString(), &ok, this);
00605 //  if ( ok )
00606 //    task->addComment( comment, _storage );
00607 //}
00608 
00609 void TaskView::reinstateTask(int completion)
00610 {
00611   Task* task = current_item();
00612   if (task == 0) {
00613     KMessageBox::information(0,i18n("No task selected."));
00614     return;
00615   }
00616 
00617   if (completion<0) completion=0;
00618   if (completion<100)
00619   {
00620     task->setPercentComplete(completion, _storage);
00621     task->setPixmapProgress();
00622     save();
00623     emit updateButtons();
00624   }
00625 }
00626 
00627 void TaskView::deleteTask(bool markingascomplete)
00628 {
00629   Task *task = current_item();
00630   if (task == 0) {
00631     KMessageBox::information(0,i18n("No task selected."));
00632     return;
00633   }
00634 
00635   int response = KMessageBox::Continue;
00636   if (!markingascomplete && _preferences->promptDelete()) {
00637     if (task->childCount() == 0) {
00638       response = KMessageBox::warningContinueCancel( 0,
00639           i18n( "Are you sure you want to delete "
00640           "the task named\n\"%1\" and its entire history?")
00641           .arg(task->name()),
00642           i18n( "Deleting Task"), KStdGuiItem::del());
00643     }
00644     else {
00645       response = KMessageBox::warningContinueCancel( 0,
00646           i18n( "Are you sure you want to delete the task named"
00647           "\n\"%1\" and its entire history?\n"
00648           "NOTE: all its subtasks and their history will also "
00649           "be deleted.").arg(task->name()),
00650           i18n( "Deleting Task"), KStdGuiItem::del());
00651     }
00652   }
00653 
00654   if (response == KMessageBox::Continue)
00655   {
00656     if (markingascomplete)
00657     {
00658       task->setPercentComplete(100, _storage);
00659       task->setPixmapProgress();
00660       save();
00661       emit updateButtons();
00662 
00663       // Have to remove after saving, as the save routine only affects tasks
00664       // that are in the view.  Otherwise, the new percent complete does not
00665       // get saved.   (No longer remove when marked as complete.)
00666       //task->removeFromView();
00667 
00668     }
00669     else
00670     {
00671       QString uid=task->uid();
00672       task->remove(activeTasks, _storage);
00673       task->removeFromView();
00674       if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed
00675       save();
00676     }
00677 
00678     // remove root decoration if there is no more children.
00679     refresh();
00680 
00681     // Stop idle detection if no more counters are running
00682     if (activeTasks.count() == 0) {
00683       _idleTimeDetector->stopIdleDetection();
00684       emit timersInactive();
00685     }
00686 
00687     emit tasksChanged( activeTasks );
00688   }
00689 }
00690 
00691 void TaskView::extractTime(int minutes)
00692 {
00693   addTimeToActiveTasks(-minutes);
00694 }
00695 
00696 void TaskView::autoSaveChanged(bool on)
00697 {
00698   if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
00699   else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
00700 }
00701 
00702 void TaskView::autoSavePeriodChanged(int /*minutes*/)
00703 {
00704   autoSaveChanged(_preferences->autoSave());
00705 }
00706 
00707 void TaskView::adaptColumns()
00708 {
00709   // to hide a column X we set it's width to 0
00710   // at that moment we'll remember the original column within
00711   // previousColumnWidths[X]
00712   //
00713   // When unhiding a previously hidden column
00714   // (previousColumnWidths[X] != HIDDEN_COLUMN !)
00715   // we restore it's width from the saved value and set
00716   // previousColumnWidths[X] to HIDDEN_COLUMN
00717 
00718   for( int x=1; x <= 4; x++) {
00719     // the column was invisible before and were switching it on now
00720     if(   _preferences->displayColumn(x-1)
00721        && previousColumnWidths[x-1] != HIDDEN_COLUMN )
00722     {
00723       setColumnWidth( x, previousColumnWidths[x-1] );
00724       previousColumnWidths[x-1] = HIDDEN_COLUMN;
00725       setColumnWidthMode( x, QListView::Maximum );
00726     }
00727     // the column was visible before and were switching it off now
00728     else
00729     if( ! _preferences->displayColumn(x-1)
00730        && previousColumnWidths[x-1] == HIDDEN_COLUMN )
00731     {
00732       setColumnWidthMode( x, QListView::Manual ); // we don't want update()
00733                                                   // to resize/unhide the col
00734       previousColumnWidths[x-1] = columnWidth( x );
00735       setColumnWidth( x, 0 );
00736     }
00737   }
00738 }
00739 
00740 void TaskView::deletingTask(Task* deletedTask)
00741 {
00742   DesktopList desktopList;
00743 
00744   _desktopTracker->registerForDesktops( deletedTask, desktopList );
00745   activeTasks.removeRef( deletedTask );
00746 
00747   emit tasksChanged( activeTasks);
00748 }
00749 
00750 void TaskView::iCalFileChanged(QString file)
00751 {
00752   kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl;
00753   stopAllTimers();
00754   _storage->save(this);
00755   load();
00756 }
00757 
00758 QValueList<HistoryEvent> TaskView::getHistory(const QDate& from,
00759     const QDate& to) const
00760 {
00761   return _storage->getHistory(from, to);
00762 }
00763 
00764 void TaskView::markTaskAsComplete()
00765 {
00766   if (current_item())
00767     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00768       << current_item()->uid() << endl;
00769   else
00770     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00771 
00772   bool markingascomplete = true;
00773   deleteTask(markingascomplete);
00774 }
00775 
00776 void TaskView::markTaskAsIncomplete()
00777 {
00778   if (current_item())
00779     kdDebug(5970) << "TaskView::markTaskAsComplete: "
00780       << current_item()->uid() << endl;
00781   else
00782     kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
00783 
00784   reinstateTask(50); // if it has been reopened, assume half-done
00785 }
00786 
00787 
00788 void TaskView::clipTotals()
00789 {
00790   TimeKard t;
00791   if (current_item() && current_item()->isRoot())
00792   {
00793     int response = KMessageBox::questionYesNo( 0,
00794         i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"),
00795         i18n("Copy Totals to Clipboard"),
00796         i18n("Copy This Task"), i18n("Copy All Tasks") );
00797     if (response == KMessageBox::Yes) // this task only
00798     {
00799       KApplication::clipboard()->setText(t.totalsAsText(this));
00800     }
00801     else // only task
00802     {
00803       KApplication::clipboard()->setText(t.totalsAsText(this, false));
00804     }
00805   }
00806   else
00807   {
00808     KApplication::clipboard()->setText(t.totalsAsText(this));
00809   }
00810 }
00811 
00812 void TaskView::clipHistory()
00813 {
00814   PrintDialog dialog;
00815   if (dialog.exec()== QDialog::Accepted)
00816   {
00817     TimeKard t;
00818     KApplication::clipboard()->
00819       setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
00820   }
00821 }
00822 
00823 #include "taskview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys