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