taskview.cpp
00001 #include <tqclipboard.h> 00002 #include <tqfile.h> 00003 #include <tqlayout.h> 00004 #include <tqlistbox.h> 00005 #include <tqlistview.h> 00006 #include <tqptrlist.h> 00007 #include <tqptrstack.h> 00008 #include <tqstring.h> 00009 #include <tqtextstream.h> 00010 #include <tqtimer.h> 00011 #include <tqxml.h> 00012 00013 #include "tdeapplication.h" // kapp 00014 #include <tdeconfig.h> 00015 #include <kdebug.h> 00016 #include <tdefiledialog.h> 00017 #include <tdelocale.h> // i18n 00018 #include <tdemessagebox.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(TQWidget *parent, const char *name, const TQString &icsfile ):TDEListView(parent,name) 00041 { 00042 _preferences = Preferences::instance( icsfile ); 00043 _storage = KarmStorage::instance(); 00044 00045 connect( this, TQT_SIGNAL( expanded( TQListViewItem * ) ), 00046 this, TQT_SLOT( itemStateChanged( TQListViewItem * ) ) ); 00047 connect( this, TQT_SIGNAL( collapsed( TQListViewItem * ) ), 00048 this, TQT_SLOT( itemStateChanged( TQListViewItem * ) ) ); 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, TQt::AlignRight ); 00060 setColumnAlignment( 2, TQt::AlignRight ); 00061 setColumnAlignment( 3, TQt::AlignRight ); 00062 setColumnAlignment( 4, TQt::AlignRight ); 00063 adaptColumns(); 00064 setAllColumnsShowFocus( true ); 00065 00066 // set up the minuteTimer 00067 _minuteTimer = new TQTimer(this); 00068 connect( _minuteTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( minuteUpdate() )); 00069 _minuteTimer->start(1000 * secsPerMinute); 00070 00071 // React when user changes iCalFile 00072 connect(_preferences, TQT_SIGNAL(iCalFile(TQString)), 00073 this, TQT_SLOT(iCalFileChanged(TQString))); 00074 00075 // resize columns when config is changed 00076 connect(_preferences, TQT_SIGNAL( setupChanged() ), this,TQT_SLOT( adaptColumns() )); 00077 00078 _minuteTimer->start(1000 * secsPerMinute); 00079 00080 // Set up the idle detection. 00081 _idleTimeDetector = new IdleTimeDetector( _preferences->idlenessTimeout() ); 00082 connect( _idleTimeDetector, TQT_SIGNAL( extractTime(int) ), 00083 this, TQT_SLOT( extractTime(int) )); 00084 connect( _idleTimeDetector, TQT_SIGNAL( stopAllTimersAt(TQDateTime) ), 00085 this, TQT_SLOT( stopAllTimersAt(TQDateTime) )); 00086 connect( _preferences, TQT_SIGNAL( idlenessTimeout(int) ), 00087 _idleTimeDetector, TQT_SLOT( setMaxIdle(int) )); 00088 connect( _preferences, TQT_SIGNAL( detectIdleness(bool) ), 00089 _idleTimeDetector, TQT_SLOT( toggleOverAllIdleDetection(bool) )); 00090 if (!_idleTimeDetector->isIdleDetectionPossible()) 00091 _preferences->disableIdleDetection(); 00092 00093 // Setup auto save timer 00094 _autoSaveTimer = new TQTimer(this); 00095 connect( _preferences, TQT_SIGNAL( autoSave(bool) ), 00096 this, TQT_SLOT( autoSaveChanged(bool) )); 00097 connect( _preferences, TQT_SIGNAL( autoSavePeriod(int) ), 00098 this, TQT_SLOT( autoSavePeriodChanged(int) )); 00099 connect( _autoSaveTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( save() )); 00100 00101 // Setup manual save timer (to save changes a little while after they happen) 00102 _manualSaveTimer = new TQTimer(this); 00103 connect( _manualSaveTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( save() )); 00104 00105 // Connect desktop tracker events to task starting/stopping 00106 _desktopTracker = new DesktopTracker(); 00107 connect( _desktopTracker, TQT_SIGNAL( reachedtActiveDesktop( Task* ) ), 00108 this, TQT_SLOT( startTimerFor(Task*) )); 00109 connect( _desktopTracker, TQT_SIGNAL( leftActiveDesktop( Task* ) ), 00110 this, TQT_SLOT( stopTimerFor(Task*) )); 00111 new TaskViewWhatsThis( this ); 00112 } 00113 00114 KarmStorage* TaskView::storage() 00115 { 00116 return _storage; 00117 } 00118 00119 void TaskView::contentsMousePressEvent ( TQMouseEvent * e ) 00120 { 00121 kdDebug(5970) << "entering contentsMousePressEvent" << endl; 00122 TDEListView::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 TDEListView. 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() == Qt::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 ( TQMouseEvent * 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 TDEListView::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( TQString 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 TQString 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 if ( _desktopTracker->startTracking() != TQString() ) 00211 KMessageBox::error( 0, i18n("You are on a too high logical desktop, desktop tracking will not work") ); 00212 _isloading = false; 00213 refresh(); 00214 } 00215 00216 void TaskView::restoreItemState( TQListViewItem *item ) 00217 { 00218 while( item ) 00219 { 00220 Task *t = (Task *)item; 00221 t->setOpen( _preferences->readBoolEntry( t->uid() ) ); 00222 if( item->childCount() > 0 ) restoreItemState( item->firstChild() ); 00223 item = item->nextSibling(); 00224 } 00225 } 00226 00227 void TaskView::itemStateChanged( TQListViewItem *item ) 00228 { 00229 if ( !item || _isloading ) return; 00230 Task *t = (Task *)item; 00231 kdDebug(5970) << "TaskView::itemStateChanged()" 00232 << " uid=" << t->uid() << " state=" << t->isOpen() 00233 << endl; 00234 if( _preferences ) _preferences->writeEntry( t->uid(), t->isOpen() ); 00235 } 00236 00237 void TaskView::closeStorage() { _storage->closeStorage( this ); } 00238 00239 void TaskView::iCalFileModified(ResourceCalendar *rc) 00240 { 00241 kdDebug(5970) << "entering iCalFileModified" << endl; 00242 kdDebug(5970) << rc->infoText() << endl; 00243 rc->dump(); 00244 _storage->buildTaskView(rc,this); 00245 kdDebug(5970) << "exiting iCalFileModified" << endl; 00246 } 00247 00248 void TaskView::refresh() 00249 { 00250 kdDebug(5970) << "entering TaskView::refresh()" << endl; 00251 this->setRootIsDecorated(true); 00252 int i = 0; 00253 for ( Task* t = item_at_index(i); t; t = item_at_index(++i) ) 00254 { 00255 t->setPixmapProgress(); 00256 } 00257 00258 // remove root decoration if there is no more children. 00259 bool anyChilds = false; 00260 for(Task* child = first_child(); 00261 child; 00262 child = child->nextSibling()) { 00263 if (child->childCount() != 0) { 00264 anyChilds = true; 00265 break; 00266 } 00267 } 00268 if (!anyChilds) { 00269 setRootIsDecorated(false); 00270 } 00271 emit updateButtons(); 00272 kdDebug(5970) << "exiting TaskView::refresh()" << endl; 00273 } 00274 00275 void TaskView::loadFromFlatFile() 00276 { 00277 kdDebug(5970) << "TaskView::loadFromFlatFile()" << endl; 00278 00279 //KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this); 00280 00281 TQString fileName(KFileDialog::getOpenFileName(TQString(), TQString(), 00282 0)); 00283 if (!fileName.isEmpty()) { 00284 TQString err = _storage->loadFromFlatFile(this, fileName); 00285 if (!err.isEmpty()) 00286 { 00287 KMessageBox::error(this, err); 00288 return; 00289 } 00290 // Register tasks with desktop tracker 00291 int task_idx = 0; 00292 Task* task = item_at_index(task_idx++); 00293 while (task) 00294 { 00295 // item_at_index returns 0 where no more items. 00296 _desktopTracker->registerForDesktops( task, task->getDesktops() ); 00297 task = item_at_index(task_idx++); 00298 } 00299 00300 setSelected(first_child(), true); 00301 setCurrentItem(first_child()); 00302 00303 if ( _desktopTracker->startTracking() != TQString() ) 00304 KMessageBox::error(0, i18n("You are on a too high logical desktop, desktop tracking will not work") ); 00305 } 00306 } 00307 00308 TQString TaskView::importPlanner(TQString fileName) 00309 { 00310 kdDebug(5970) << "entering importPlanner" << endl; 00311 PlannerParser* handler=new PlannerParser(this); 00312 if (fileName.isEmpty()) fileName=KFileDialog::getOpenFileName(TQString(), TQString(), 0); 00313 TQFile xmlFile( fileName ); 00314 TQXmlInputSource source( xmlFile ); 00315 TQXmlSimpleReader reader; 00316 reader.setContentHandler( handler ); 00317 reader.parse( source ); 00318 refresh(); 00319 return ""; 00320 } 00321 00322 TQString TaskView::report( const ReportCriteria& rc ) 00323 { 00324 return _storage->report( this, rc ); 00325 } 00326 00327 void TaskView::exportcsvFile() 00328 { 00329 kdDebug(5970) << "TaskView::exportcsvFile()" << endl; 00330 00331 CSVExportDialog dialog( ReportCriteria::CSVTotalsExport, this ); 00332 if ( current_item() && current_item()->isRoot() ) 00333 dialog.enableTasksToExportQuestion(); 00334 dialog.urlExportTo->KURLRequester::setMode(KFile::File); 00335 if ( dialog.exec() ) { 00336 TQString err = _storage->report( this, dialog.reportCriteria() ); 00337 if ( !err.isEmpty() ) KMessageBox::error( this, i18n(err.ascii()) ); 00338 } 00339 } 00340 00341 TQString TaskView::exportcsvHistory() 00342 { 00343 kdDebug(5970) << "TaskView::exportcsvHistory()" << endl; 00344 TQString err; 00345 00346 CSVExportDialog dialog( ReportCriteria::CSVHistoryExport, this ); 00347 if ( current_item() && current_item()->isRoot() ) 00348 dialog.enableTasksToExportQuestion(); 00349 dialog.urlExportTo->KURLRequester::setMode(KFile::File); 00350 if ( dialog.exec() ) { 00351 err = _storage->report( this, dialog.reportCriteria() ); 00352 } 00353 return err; 00354 } 00355 00356 void TaskView::scheduleSave() 00357 { 00358 kdDebug(5970) << "Entering TaskView::scheduleSave" << endl; 00359 // save changes a little while after they happen 00360 _manualSaveTimer->start( 10, true /*single-shot*/ ); 00361 } 00362 00363 Preferences* TaskView::preferences() { return _preferences; } 00364 00365 TQString TaskView::save() 00366 // This saves the tasks. If they do not yet have an endDate, their startDate is also not saved. 00367 { 00368 kdDebug(5970) << "Entering TaskView::save" << endl; 00369 TQString err = _storage->save(this); 00370 emit(setStatusBar(err)); 00371 return err; 00372 } 00373 00374 void TaskView::startCurrentTimer() 00375 { 00376 startTimerFor( current_item() ); 00377 } 00378 00379 long TaskView::count() 00380 { 00381 long n = 0; 00382 for (Task* t = item_at_index(n); t; t=item_at_index(++n)); 00383 return n; 00384 } 00385 00386 void TaskView::startTimerFor(Task* task, TQDateTime startTime ) 00387 { 00388 kdDebug(5970) << "Entering TaskView::startTimerFor" << endl; 00389 if (save()==TQString()) 00390 { 00391 if (task != 0 && activeTasks.findRef(task) == -1) 00392 { 00393 _idleTimeDetector->startIdleDetection(); 00394 if (!task->isComplete()) 00395 { 00396 task->setRunning(true, _storage, startTime); 00397 activeTasks.append(task); 00398 emit updateButtons(); 00399 if ( activeTasks.count() == 1 ) 00400 emit timersActive(); 00401 emit tasksChanged( activeTasks); 00402 } 00403 } 00404 } 00405 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 ~/.trinity/share/apps/tdeabc/lock.")); 00406 } 00407 00408 void TaskView::clearActiveTasks() 00409 { 00410 activeTasks.clear(); 00411 } 00412 00413 void TaskView::stopAllTimers() 00414 { 00415 kdDebug(5970) << "Entering TaskView::stopAllTimers()" << endl; 00416 for ( unsigned int i = 0; i < activeTasks.count(); i++ ) 00417 activeTasks.at(i)->setRunning(false, _storage); 00418 00419 _idleTimeDetector->stopIdleDetection(); 00420 activeTasks.clear(); 00421 emit updateButtons(); 00422 emit timersInactive(); 00423 emit tasksChanged( activeTasks ); 00424 } 00425 00426 void TaskView::stopAllTimersAt(TQDateTime qdt) 00427 // stops all timers for the time qdt. This makes sense, if the idletimedetector detected 00428 // the last work has been done 50 minutes ago. 00429 { 00430 kdDebug(5970) << "Entering TaskView::stopAllTimersAt " << qdt << endl; 00431 for ( unsigned int i = 0; i < activeTasks.count(); i++ ) 00432 { 00433 activeTasks.at(i)->setRunning(false, _storage, qdt, qdt); 00434 kdDebug() << activeTasks.at(i)->name() << endl; 00435 } 00436 00437 _idleTimeDetector->stopIdleDetection(); 00438 activeTasks.clear(); 00439 emit updateButtons(); 00440 emit timersInactive(); 00441 emit tasksChanged( activeTasks ); 00442 } 00443 00444 void TaskView::startNewSession() 00445 { 00446 TQListViewItemIterator item( first_child()); 00447 for ( ; item.current(); ++item ) { 00448 Task * task = (Task *) item.current(); 00449 task->startNewSession(); 00450 } 00451 } 00452 00453 void TaskView::resetTimeForAllTasks() 00454 { 00455 TQListViewItemIterator item( first_child()); 00456 for ( ; item.current(); ++item ) { 00457 Task * task = (Task *) item.current(); 00458 task->resetTimes(); 00459 } 00460 } 00461 00462 void TaskView::stopTimerFor(Task* task) 00463 { 00464 kdDebug(5970) << "Entering stopTimerFor. task = " << task->name() << endl; 00465 if ( task != 0 && activeTasks.findRef(task) != -1 ) { 00466 activeTasks.removeRef(task); 00467 task->setRunning(false, _storage); 00468 if ( activeTasks.count() == 0 ) { 00469 _idleTimeDetector->stopIdleDetection(); 00470 emit timersInactive(); 00471 } 00472 emit updateButtons(); 00473 } 00474 emit tasksChanged( activeTasks); 00475 } 00476 00477 void TaskView::stopCurrentTimer() 00478 { 00479 stopTimerFor( current_item()); 00480 } 00481 00482 void TaskView::minuteUpdate() 00483 { 00484 addTimeToActiveTasks(1, false); 00485 } 00486 00487 void TaskView::addTimeToActiveTasks(int minutes, bool save_data) 00488 { 00489 for( unsigned int i = 0; i < activeTasks.count(); i++ ) 00490 activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) ); 00491 } 00492 00493 void TaskView::newTask() 00494 { 00495 newTask(i18n("New Task"), 0); 00496 } 00497 00498 void TaskView::newTask(TQString caption, Task *parent) 00499 { 00500 EditTaskDialog *dialog = new EditTaskDialog(caption, false); 00501 long total, totalDiff, session, sessionDiff; 00502 DesktopList desktopList; 00503 00504 int result = dialog->exec(); 00505 if ( result == TQDialog::Accepted ) { 00506 TQString taskName = i18n( "Unnamed Task" ); 00507 if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName(); 00508 00509 total = totalDiff = session = sessionDiff = 0; 00510 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList ); 00511 00512 // If all available desktops are checked, disable auto tracking, 00513 // since it makes no sense to track for every desktop. 00514 if ( desktopList.size() == ( unsigned int ) _desktopTracker->desktopCount() ) 00515 desktopList.clear(); 00516 00517 TQString uid = addTask( taskName, total, session, desktopList, parent ); 00518 if ( uid.isNull() ) 00519 { 00520 KMessageBox::error( 0, i18n( 00521 "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 ~/.trinity/share/apps/tdeabc/lock/ " ) ); 00522 } 00523 00524 delete dialog; 00525 } 00526 } 00527 00528 TQString TaskView::addTask 00529 ( const TQString& taskname, long total, long session, 00530 const DesktopList& desktops, Task* parent ) 00531 { 00532 Task *task; 00533 kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl; 00534 00535 if ( parent ) task = new Task( taskname, total, session, desktops, parent ); 00536 else task = new Task( taskname, total, session, desktops, this ); 00537 00538 task->setUid( _storage->addTask( task, parent ) ); 00539 TQString taskuid=task->uid(); 00540 if ( ! taskuid.isNull() ) 00541 { 00542 _desktopTracker->registerForDesktops( task, desktops ); 00543 setCurrentItem( task ); 00544 setSelected( task, true ); 00545 task->setPixmapProgress(); 00546 save(); 00547 } 00548 else 00549 { 00550 delete task; 00551 } 00552 return taskuid; 00553 } 00554 00555 void TaskView::newSubTask() 00556 { 00557 Task* task = current_item(); 00558 if(!task) 00559 return; 00560 newTask(i18n("New Sub Task"), task); 00561 task->setOpen(true); 00562 refresh(); 00563 } 00564 00565 void TaskView::editTask() 00566 { 00567 Task *task = current_item(); 00568 if (!task) 00569 return; 00570 00571 DesktopList desktopList = task->getDesktops(); 00572 EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList); 00573 dialog->setTask( task->name(), 00574 task->time(), 00575 task->sessionTime() ); 00576 int result = dialog->exec(); 00577 if (result == TQDialog::Accepted) { 00578 TQString taskName = i18n("Unnamed Task"); 00579 if (!dialog->taskName().isEmpty()) { 00580 taskName = dialog->taskName(); 00581 } 00582 // setName only does something if the new name is different 00583 task->setName(taskName, _storage); 00584 00585 // update session time as well if the time was changed 00586 long total, session, totalDiff, sessionDiff; 00587 total = totalDiff = session = sessionDiff = 0; 00588 DesktopList desktopList; 00589 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList); 00590 00591 if( totalDiff != 0 || sessionDiff != 0) 00592 task->changeTimes( sessionDiff, totalDiff, _storage ); 00593 00594 // If all available desktops are checked, disable auto tracking, 00595 // since it makes no sense to track for every desktop. 00596 if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount()) 00597 desktopList.clear(); 00598 00599 task->setDesktopList(desktopList); 00600 00601 _desktopTracker->registerForDesktops( task, desktopList ); 00602 00603 emit updateButtons(); 00604 } 00605 delete dialog; 00606 } 00607 00608 //void TaskView::addCommentToTask() 00609 //{ 00610 // Task *task = current_item(); 00611 // if (!task) 00612 // return; 00613 00614 // bool ok; 00615 // TQString comment = KLineEditDlg::getText(i18n("Comment"), 00616 // i18n("Log comment for task '%1':").arg(task->name()), 00617 // TQString(), &ok, this); 00618 // if ( ok ) 00619 // task->addComment( comment, _storage ); 00620 //} 00621 00622 void TaskView::reinstateTask(int completion) 00623 { 00624 Task* task = current_item(); 00625 if (task == 0) { 00626 KMessageBox::information(0,i18n("No task selected.")); 00627 return; 00628 } 00629 00630 if (completion<0) completion=0; 00631 if (completion<100) 00632 { 00633 task->setPercentComplete(completion, _storage); 00634 task->setPixmapProgress(); 00635 save(); 00636 emit updateButtons(); 00637 } 00638 } 00639 00640 void TaskView::deleteTask(bool markingascomplete) 00641 { 00642 Task *task = current_item(); 00643 if (task == 0) { 00644 KMessageBox::information(0,i18n("No task selected.")); 00645 return; 00646 } 00647 00648 int response = KMessageBox::Continue; 00649 if (!markingascomplete && _preferences->promptDelete()) { 00650 if (task->childCount() == 0) { 00651 response = KMessageBox::warningContinueCancel( 0, 00652 i18n( "Are you sure you want to delete " 00653 "the task named\n\"%1\" and its entire history?") 00654 .arg(task->name()), 00655 i18n( "Deleting Task"), KStdGuiItem::del()); 00656 } 00657 else { 00658 response = KMessageBox::warningContinueCancel( 0, 00659 i18n( "Are you sure you want to delete the task named" 00660 "\n\"%1\" and its entire history?\n" 00661 "NOTE: all its subtasks and their history will also " 00662 "be deleted.").arg(task->name()), 00663 i18n( "Deleting Task"), KStdGuiItem::del()); 00664 } 00665 } 00666 00667 if (response == KMessageBox::Continue) 00668 { 00669 if (markingascomplete) 00670 { 00671 task->setPercentComplete(100, _storage); 00672 task->setPixmapProgress(); 00673 save(); 00674 emit updateButtons(); 00675 00676 // Have to remove after saving, as the save routine only affects tasks 00677 // that are in the view. Otherwise, the new percent complete does not 00678 // get saved. (No longer remove when marked as complete.) 00679 //task->removeFromView(); 00680 00681 } 00682 else 00683 { 00684 TQString uid=task->uid(); 00685 task->remove(activeTasks, _storage); 00686 task->removeFromView(); 00687 if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed 00688 save(); 00689 } 00690 00691 // remove root decoration if there is no more children. 00692 refresh(); 00693 00694 // Stop idle detection if no more counters are running 00695 if (activeTasks.count() == 0) { 00696 _idleTimeDetector->stopIdleDetection(); 00697 emit timersInactive(); 00698 } 00699 00700 emit tasksChanged( activeTasks ); 00701 } 00702 } 00703 00704 void TaskView::extractTime(int minutes) 00705 // This procedure subtracts ''minutes'' from the active task's time in the memory. 00706 // It is called by the idletimedetector class. 00707 // When the desktop has been idle for the past 20 minutes, the past 20 minutes have 00708 // already been added to the task's time in order for the time to be displayed correctly. 00709 // That is why idletimedetector needs to subtract this time first. 00710 { 00711 kdDebug(5970) << "Entering extractTime" << endl; 00712 addTimeToActiveTasks(-minutes,false); // subtract minutes, but do not store it 00713 } 00714 00715 void TaskView::autoSaveChanged(bool on) 00716 { 00717 if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute); 00718 else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop(); 00719 } 00720 00721 void TaskView::autoSavePeriodChanged(int /*minutes*/) 00722 { 00723 autoSaveChanged(_preferences->autoSave()); 00724 } 00725 00726 void TaskView::adaptColumns() 00727 { 00728 // to hide a column X we set it's width to 0 00729 // at that moment we'll remember the original column within 00730 // previousColumnWidths[X] 00731 // 00732 // When unhiding a previously hidden column 00733 // (previousColumnWidths[X] != HIDDEN_COLUMN !) 00734 // we restore it's width from the saved value and set 00735 // previousColumnWidths[X] to HIDDEN_COLUMN 00736 00737 for( int x=1; x <= 4; x++) { 00738 // the column was invisible before and were switching it on now 00739 if( _preferences->displayColumn(x-1) 00740 && previousColumnWidths[x-1] != HIDDEN_COLUMN ) 00741 { 00742 setColumnWidth( x, previousColumnWidths[x-1] ); 00743 previousColumnWidths[x-1] = HIDDEN_COLUMN; 00744 setColumnWidthMode( x, TQListView::Maximum ); 00745 } 00746 // the column was visible before and were switching it off now 00747 else 00748 if( ! _preferences->displayColumn(x-1) 00749 && previousColumnWidths[x-1] == HIDDEN_COLUMN ) 00750 { 00751 setColumnWidthMode( x, TQListView::Manual ); // we don't want update() 00752 // to resize/unhide the col 00753 previousColumnWidths[x-1] = columnWidth( x ); 00754 setColumnWidth( x, 0 ); 00755 } 00756 } 00757 } 00758 00759 void TaskView::deletingTask(Task* deletedTask) 00760 { 00761 DesktopList desktopList; 00762 00763 _desktopTracker->registerForDesktops( deletedTask, desktopList ); 00764 activeTasks.removeRef( deletedTask ); 00765 00766 emit tasksChanged( activeTasks); 00767 } 00768 00769 void TaskView::iCalFileChanged(TQString file) 00770 // User might have picked a new file in the preferences dialog. 00771 // This is not iCalFileModified. 00772 { 00773 kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl; 00774 if (_storage->icalfile() != file) 00775 { 00776 stopAllTimers(); 00777 _storage->save(this); 00778 load(); 00779 } 00780 } 00781 00782 TQValueList<HistoryEvent> TaskView::getHistory(const TQDate& from, 00783 const TQDate& to) const 00784 { 00785 return _storage->getHistory(from, to); 00786 } 00787 00788 void TaskView::markTaskAsComplete() 00789 { 00790 if (current_item()) 00791 kdDebug(5970) << "TaskView::markTaskAsComplete: " 00792 << current_item()->uid() << endl; 00793 else 00794 kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl; 00795 00796 bool markingascomplete = true; 00797 deleteTask(markingascomplete); 00798 } 00799 00800 void TaskView::markTaskAsIncomplete() 00801 { 00802 if (current_item()) 00803 kdDebug(5970) << "TaskView::markTaskAsComplete: " 00804 << current_item()->uid() << endl; 00805 else 00806 kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl; 00807 00808 reinstateTask(50); // if it has been reopened, assume half-done 00809 } 00810 00811 00812 void TaskView::clipTotals() 00813 { 00814 TimeKard t; 00815 if (current_item() && current_item()->isRoot()) 00816 { 00817 int response = KMessageBox::questionYesNo( 0, 00818 i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"), 00819 i18n("Copy Totals to Clipboard"), 00820 i18n("Copy This Task"), i18n("Copy All Tasks") ); 00821 if (response == KMessageBox::Yes) // This task only 00822 { 00823 TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime)); 00824 } 00825 else // All tasks 00826 { 00827 TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::TotalTime)); 00828 } 00829 } 00830 else 00831 { 00832 TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime)); 00833 } 00834 } 00835 00836 void TaskView::clipSession() 00837 { 00838 TimeKard t; 00839 if (current_item() && current_item()->isRoot()) 00840 { 00841 int response = KMessageBox::questionYesNo( 0, 00842 i18n("Copy session time for just this task and its subtasks, or copy session time for all tasks?"), 00843 i18n("Copy Session Time to Clipboard"), 00844 i18n("Copy This Task"), i18n("Copy All Tasks") ); 00845 if (response == KMessageBox::Yes) // this task only 00846 { 00847 TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime)); 00848 } 00849 else // only task 00850 { 00851 TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::SessionTime)); 00852 } 00853 } 00854 else 00855 { 00856 TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime)); 00857 } 00858 } 00859 00860 void TaskView::clipHistory() 00861 { 00862 PrintDialog dialog; 00863 if (dialog.exec()== TQDialog::Accepted) 00864 { 00865 TimeKard t; 00866 TDEApplication::clipboard()-> 00867 setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) ); 00868 } 00869 } 00870 00871 #include "taskview.moc"