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