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