00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "taskview.h"
00023
00024 #include <cassert>
00025
00026 #include <QFile>
00027 #include <QStyledItemDelegate>
00028 #include <QMenu>
00029 #include <QPainter>
00030 #include <QString>
00031 #include <QTimer>
00032 #include <QMouseEvent>
00033 #include <QList>
00034 #include <QClipboard>
00035
00036 #include <KApplication>
00037 #include <KDebug>
00038 #include <KFileDialog>
00039 #include <KLocale>
00040 #include <KMessageBox>
00041 #include <KUrlRequester>
00042
00043 #include "csvexportdialog.h"
00044 #include "desktoptracker.h"
00045 #include "edittaskdialog.h"
00046 #include "idletimedetector.h"
00047 #include "plannerparser.h"
00048 #include "preferences.h"
00049 #include "ktimetracker.h"
00050 #include "task.h"
00051 #include "timekard.h"
00052 #include "treeviewheadercontextmenu.h"
00053 #include "focusdetector.h"
00054 #include "focusdetectornotifier.h"
00055 #include "storageadaptor.h"
00056
00057 #define T_LINESIZE 1023
00058
00059 class DesktopTracker;
00060
00061
00062 class TaskViewDelegate : public QStyledItemDelegate {
00063 public:
00064 TaskViewDelegate( QObject *parent = 0 ) : QStyledItemDelegate( parent ) {}
00065
00066 void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const {
00067 if (index.column () == 6) {
00068 QApplication::style()->drawControl( QStyle::CE_ItemViewItem, &option, painter );
00069 int rX = option.rect.x() + 2;
00070 int rY = option.rect.y() + 2;
00071 int rWidth = option.rect.width() - 4;
00072 int rHeight = option.rect.height() - 4;
00073
00074 int value = index.model()->data( index ).toInt();
00075 int newWidth = (int)(rWidth * (value / 100.));
00076
00077 if(QApplication::isLeftToRight())
00078 {
00079 int mid = rY + rHeight / 2;
00080 int width = rWidth / 2;
00081 QLinearGradient gradient1( rX, mid, rX + width, mid);
00082 gradient1.setColorAt( 0, Qt::red );
00083 gradient1.setColorAt( 1, Qt::yellow );
00084 painter->fillRect( rX, rY, (newWidth < width) ? newWidth : width, rHeight, gradient1 );
00085
00086 if (newWidth > width) {
00087 QLinearGradient gradient2( rX + width, mid, rX + 2 * width, mid);
00088 gradient2.setColorAt( 0, Qt::yellow );
00089 gradient2.setColorAt( 1, Qt::green );
00090 painter->fillRect( rX + width, rY, newWidth - width, rHeight, gradient2 );
00091 }
00092
00093 painter->setPen( option.state & QStyle::State_Selected ? option.palette.highlight().color() : option.palette.background().color() );
00094 for (int x = rHeight; x < newWidth; x += rHeight) {
00095 painter->drawLine( rX + x, rY, rX + x, rY + rHeight - 1 );
00096 }
00097 }
00098 else
00099 {
00100 int mid = option.rect.height() - rHeight / 2;
00101 int width = rWidth / 2;
00102 QLinearGradient gradient1( rX, mid, rX + width, mid);
00103 gradient1.setColorAt( 0, Qt::red );
00104 gradient1.setColorAt( 1, Qt::yellow );
00105 painter->fillRect( option.rect.height(), rY, (newWidth < width) ? newWidth : width, rHeight, gradient1 );
00106
00107 if (newWidth > width) {
00108 QLinearGradient gradient2( rX + width, mid, rX + 2 * width, mid);
00109 gradient2.setColorAt( 0, Qt::yellow );
00110 gradient2.setColorAt( 1, Qt::green );
00111 painter->fillRect( rX + width, rY, newWidth - width, rHeight, gradient2 );
00112 }
00113
00114 painter->setPen( option.state & QStyle::State_Selected ? option.palette.highlight().color() : option.palette.background().color() );
00115 for (int x = rWidth- rHeight; x > newWidth; x -= rHeight) {
00116 painter->drawLine( rWidth - x, rY, rWidth - x, rY + rHeight - 1 );
00117 }
00118
00119 }
00120 painter->setPen( Qt::black );
00121 painter->drawText( option.rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(value) + " %" );
00122 } else {
00123 QStyledItemDelegate::paint( painter, option, index );
00124 }
00125 }
00126 };
00127
00128
00129
00130
00131 class TaskView::Private {
00132 public:
00133 Private() :
00134 mStorage( new KarmStorage() ),
00135 mFocusTrackingActive( false ) {}
00136
00137 ~Private() {
00138 delete mStorage;
00139 }
00140 KarmStorage *mStorage;
00141 bool mFocusTrackingActive;
00142 Task* mLastTaskWithFocus;
00143 QList<Task*> mActiveTasks;
00144
00145 QMenu *mPopupPercentageMenu;
00146 QMap<QAction*, int> mPercentage;
00147 QMenu *mPopupPriorityMenu;
00148 QMap<QAction*, int> mPriority;
00149 };
00150
00151
00152
00153 TaskView::TaskView( QWidget *parent ) : QTreeWidget(parent), d( new Private() )
00154 {
00155 _preferences = Preferences::instance();
00156 new StorageAdaptor( this );
00157 QDBusConnection::sessionBus().registerObject( "/ktimetrackerstorage", this );
00158
00159 connect( this, SIGNAL(itemExpanded(QTreeWidgetItem*)),
00160 this, SLOT(itemStateChanged(QTreeWidgetItem*)) );
00161 connect( this, SIGNAL(itemCollapsed(QTreeWidgetItem*)),
00162 this, SLOT(itemStateChanged(QTreeWidgetItem*)) );
00163 connect( this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
00164 this, SLOT(slotItemDoubleClicked(QTreeWidgetItem*, int)) );
00165 connect( FocusDetectorNotifier::instance()->focusDetector(),
00166 SIGNAL( newFocus( const QString & ) ),
00167 this, SLOT( newFocusWindowDetected ( const QString & ) ) );
00168
00169 QStringList labels;
00170 setWindowFlags( windowFlags() | Qt::WindowContextHelpButtonHint );
00171 labels << i18n( "Task Name" ) << i18n( "Session Time" ) << i18n( "Time" )
00172 << i18n( "Total Session Time" ) << i18n( "Total Time" )
00173 << i18n( "Priority" ) << i18n( "Percent Complete" );
00174 setHeaderLabels( labels );
00175 headerItem()->setWhatsThis(0,"The task name is how you call the task, it can be chosen freely.");
00176 headerItem()->setWhatsThis(1,"The session time is the time since you last chose \"start new session.\"");
00177 headerItem()->setWhatsThis(3,"The total session time is the session time of this task and all its subtasks.");
00178 headerItem()->setWhatsThis(4,"The total time is the time of this task and all its subtasks.");
00179 setAllColumnsShowFocus( true );
00180 setSortingEnabled( true );
00181 setAlternatingRowColors( true );
00182 setDragDropMode( QAbstractItemView::InternalMove );
00183 setItemDelegateForColumn( 6, new TaskViewDelegate(this) );
00184
00185
00186 _minuteTimer = new QTimer(this);
00187 connect( _minuteTimer, SIGNAL( timeout() ), this, SLOT( minuteUpdate() ));
00188 _minuteTimer->start(1000 * secsPerMinute);
00189
00190
00191 _idleTimeDetector = new IdleTimeDetector( KTimeTrackerSettings::period() );
00192 connect( _idleTimeDetector, SIGNAL( extractTime(int) ),
00193 this, SLOT( extractTime(int) ));
00194 connect( _idleTimeDetector, SIGNAL( stopAllTimers(QDateTime) ),
00195 this, SLOT( stopAllTimers(QDateTime) ));
00196 if (!_idleTimeDetector->isIdleDetectionPossible())
00197 KTimeTrackerSettings::setEnabled( false );
00198
00199
00200 _autoSaveTimer = new QTimer(this);
00201 connect( _autoSaveTimer, SIGNAL( timeout() ), this, SLOT( save() ));
00202
00203
00204 _manualSaveTimer = new QTimer(this);
00205 _manualSaveTimer->setSingleShot( true );
00206 connect( _manualSaveTimer, SIGNAL( timeout() ), this, SLOT( save() ));
00207
00208
00209 _desktopTracker = new DesktopTracker();
00210 connect( _desktopTracker, SIGNAL( reachedActiveDesktop( Task* ) ),
00211 this, SLOT( startTimerFor(Task*) ));
00212 connect( _desktopTracker, SIGNAL( leftActiveDesktop( Task* ) ),
00213 this, SLOT( stopTimerFor(Task*) ));
00214
00215
00216 TreeViewHeaderContextMenu *headerContextMenu = new TreeViewHeaderContextMenu( this, this, TreeViewHeaderContextMenu::AlwaysCheckBox, QVector<int>() << 0 );
00217 connect( headerContextMenu, SIGNAL(columnToggled(int)), this, SLOT(slotColumnToggled(int)) );
00218
00219
00220 d->mPopupPercentageMenu = new QMenu( this );
00221 for ( int i = 0; i <= 100; i += 10 )
00222 {
00223 QString label = i18n( "%1 %" , i );
00224 d->mPercentage[ d->mPopupPercentageMenu->addAction( label ) ] = i;
00225 }
00226 connect( d->mPopupPercentageMenu, SIGNAL( triggered( QAction * ) ),
00227 this, SLOT( slotSetPercentage( QAction * ) ) );
00228
00229 d->mPopupPriorityMenu = new QMenu( this );
00230 for ( int i = 0; i <= 9; ++i ) {
00231 QString label;
00232 switch ( i ) {
00233 case 0:
00234 label = i18n( "unspecified" );
00235 break;
00236 case 1:
00237 label = i18nc( "combox entry for highest priority", "1 (highest)" );
00238 break;
00239 case 5:
00240 label = i18nc( "combox entry for medium priority", "5 (medium)" );
00241 break;
00242 case 9:
00243 label = i18nc( "combox entry for lowest priority", "9 (lowest)" );
00244 break;
00245 default:
00246 label = QString( "%1" ).arg( i );
00247 break;
00248 }
00249 d->mPriority[ d->mPopupPriorityMenu->addAction( label ) ] = i;
00250 }
00251 connect( d->mPopupPriorityMenu, SIGNAL( triggered( QAction * ) ),
00252 this, SLOT( slotSetPriority( QAction * ) ) );
00253
00254 setContextMenuPolicy( Qt::CustomContextMenu );
00255 connect( this, SIGNAL( customContextMenuRequested( const QPoint & ) ),
00256 this, SLOT( slotCustomContextMenuRequested( const QPoint & ) ) );
00257
00258 reconfigure();
00259 sortByColumn( 0, Qt::AscendingOrder );
00260 for (int i=0; i<=columnCount(); i++) resizeColumnToContents(i);
00261 }
00262
00263 void TaskView::newFocusWindowDetected( const QString &taskName )
00264 {
00265 QString newTaskName = taskName;
00266 newTaskName.replace( "\n", "" );
00267
00268 if ( d->mFocusTrackingActive ) {
00269 bool found = false;
00270 stopTimerFor( d->mLastTaskWithFocus );
00271 int i = 0;
00272 for ( Task* task = itemAt( i ); task; task = itemAt( ++i ) ) {
00273 if ( task->name() == newTaskName ) {
00274 found = true;
00275 startTimerFor( task );
00276 d->mLastTaskWithFocus = task;
00277 }
00278 }
00279 if ( !found ) {
00280 QString taskuid = addTask( newTaskName );
00281 if ( taskuid.isNull() ) {
00282 KMessageBox::error( 0, i18n(
00283 "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/ " ) );
00284 }
00285 i = 0;
00286 for ( Task* task = itemAt( i ); task; task = itemAt( ++i ) ) {
00287 if (task->name() == newTaskName) {
00288 startTimerFor( task );
00289 d->mLastTaskWithFocus = task;
00290 }
00291 }
00292 }
00293 emit updateButtons();
00294 }
00295 }
00296
00297 void TaskView::mouseMoveEvent( QMouseEvent *event )
00298 {
00299 QModelIndex index = indexAt( event->pos() );
00300
00301 if (index.isValid() && index.column() == 6)
00302 {
00303 int newValue = (int)((event->pos().x() - visualRect(index).x()) / (double)(visualRect(index).width()) * 100);
00304
00305 if ( event->modifiers() & Qt::ShiftModifier ) {
00306 int delta = newValue % 10;
00307 if ( delta >= 5 ) {
00308 newValue += (10 - delta);
00309 } else {
00310 newValue -= delta;
00311 }
00312 }
00313
00314 QTreeWidgetItem *item = itemFromIndex( index );
00315 if (item && item->isSelected())
00316 {
00317 Task *task = static_cast<Task*>(item);
00318 if (task)
00319 {
00320 task->setPercentComplete( newValue, d->mStorage );
00321
00322 emit updateButtons();
00323 }
00324 }
00325 }
00326 else
00327 {
00328 QTreeWidget::mouseMoveEvent( event );
00329 }
00330 }
00331
00332 void TaskView::mousePressEvent( QMouseEvent *event )
00333 {
00334 QModelIndex index = indexAt( event->pos() );
00335
00336
00337 if ( index.isValid()
00338 && index.column() == 0
00339 && visualRect( index ).x() <= event->pos().x()
00340 && event->pos().x() < visualRect( index ).x() + 19)
00341 {
00342 QTreeWidgetItem *item = itemFromIndex( index );
00343 if (item)
00344 {
00345 Task *task = static_cast<Task*>(item);
00346 if (task)
00347 {
00348 if (task->isComplete()) task->setPercentComplete( 0, d->mStorage );
00349 else
00350 {
00351 task->setPercentComplete( 100, d->mStorage );
00352 }
00353
00354 emit updateButtons();
00355 }
00356 }
00357 }
00358 else
00359 {
00360 if ( KTimeTrackerSettings::configPDA() )
00361
00362 {
00363 QPoint newPos = viewport()->mapToGlobal( event->pos() );
00364 emit contextMenuRequested( newPos );
00365 }
00366 QTreeWidget::mousePressEvent( event );
00367 }
00368 }
00369
00370 KarmStorage* TaskView::storage()
00371 {
00372 return d->mStorage;
00373 }
00374
00375 TaskView::~TaskView()
00376 {
00377 FocusDetectorNotifier::instance()->detach( this );
00378 delete d;
00379 KTimeTrackerSettings::self()->writeConfig();
00380 }
00381
00382 Task* TaskView::currentItem() const
00383 {
00384 kDebug(5970) << "Entering function";
00385 return static_cast< Task* >( QTreeWidget::currentItem() );
00386 }
00387
00388 Task* TaskView::itemAt(int i)
00389
00390
00391
00392 {
00393 if ( topLevelItemCount() == 0 ) return 0;
00394
00395 QTreeWidgetItemIterator item( this );
00396 while( *item && i-- ) ++item;
00397
00398 kDebug( 5970 ) << "Leaving TaskView::itemAt" << "returning " << (*item==0);
00399 if ( !( *item ) )
00400 return 0;
00401 else
00402 return (Task*)*item;
00403 }
00404
00405 void TaskView::load( const QString &fileName )
00406 {
00407 assert( !( fileName.isEmpty() ) );
00408
00409
00410
00411 kDebug(5970) << "Entering function";
00412 _isloading = true;
00413 QString err = d->mStorage->load(this, fileName);
00414
00415 if (!err.isEmpty())
00416 {
00417 KMessageBox::error(this, err);
00418 _isloading = false;
00419 kDebug(5970) << "Leaving TaskView::load";
00420 return;
00421 }
00422
00423
00424 int i = 0;
00425 for ( Task* t = itemAt(i); t; t = itemAt(++i) )
00426 _desktopTracker->registerForDesktops( t, t->desktops() );
00427
00428
00429 i = 0;
00430 for ( Task* t = itemAt(i); t; t = itemAt(++i) )
00431 {
00432 if ( !d->mStorage->allEventsHaveEndTiMe( t ) )
00433 {
00434 t->resumeRunning();
00435 d->mActiveTasks.append(t);
00436 emit updateButtons();
00437 if ( d->mActiveTasks.count() == 1 )
00438 emit timersActive();
00439 emit tasksChanged( d->mActiveTasks );
00440 }
00441 }
00442
00443
00444 if ( topLevelItemCount() > 0 )
00445 {
00446 restoreItemState();
00447 setCurrentItem(topLevelItem( 0 ));
00448 if ( !_desktopTracker->startTracking().isEmpty() )
00449 KMessageBox::error( 0, i18n( "Your virtual desktop number is too high, desktop tracking will not work" ) );
00450 _isloading = false;
00451 refresh();
00452 }
00453 for (int i=0; i<=columnCount(); i++) resizeColumnToContents(i);
00454 kDebug(5970) << "Leaving function";
00455 }
00456
00457 void TaskView::restoreItemState()
00458
00459
00460
00461 {
00462 kDebug(5970) << "Entering function";
00463
00464 if ( topLevelItemCount() > 0 ) {
00465 QTreeWidgetItemIterator item( this );
00466 while( *item )
00467 {
00468 Task *t = (Task *) *item;
00469 t->setExpanded( _preferences->readBoolEntry( t->uid() ) );
00470 ++item;
00471 }
00472 }
00473 kDebug(5970) << "Leaving function";
00474 }
00475
00476 void TaskView::itemStateChanged( QTreeWidgetItem *item )
00477 {
00478 kDebug() << "Entering function";
00479 if ( !item || _isloading ) return;
00480 Task *t = (Task *)item;
00481 kDebug(5970) <<"TaskView::itemStateChanged()" <<" uid=" << t->uid() <<" state=" << t->isExpanded();
00482 if( _preferences ) _preferences->writeEntry( t->uid(), t->isExpanded() );
00483 }
00484
00485 void TaskView::closeStorage() { d->mStorage->closeStorage(); }
00486
00487 bool TaskView::allEventsHaveEndTiMe()
00488 {
00489 return d->mStorage->allEventsHaveEndTiMe();
00490 }
00491
00492 void TaskView::iCalFileModified(ResourceCalendar *rc)
00493 {
00494 kDebug(5970) << "entering function";
00495 kDebug(5970) << rc->infoText();
00496 rc->dump();
00497 d->mStorage->buildTaskView(rc,this);
00498 kDebug(5970) << "exiting iCalFileModified";
00499 }
00500
00501 void TaskView::refresh()
00502 {
00503 kDebug(5970) << "entering function";
00504 int i = 0;
00505 for ( Task* t = itemAt(i); t; t = itemAt(++i) )
00506 {
00507 t->setPixmapProgress();
00508 t->update();
00509 }
00510
00511
00512 i = 0;
00513 while ( itemAt( ++i ) && ( itemAt( i )->depth() == 0 ) ){};
00514
00515
00516
00517 setRootIsDecorated( true );
00518
00519 emit updateButtons();
00520 kDebug(5970) << "exiting TaskView::refresh()";
00521 }
00522
00523 QString TaskView::reFreshTimes()
00525 {
00526 kDebug(5970) << "Entering function";
00527 QString err;
00528
00529
00530
00531 KCal::Event::List eventList = storage()->rawevents();
00532 int n=-1;
00533 resetTimeForAllTasks();
00534 emit reSetTimes();
00535 while (itemAt(++n))
00536 {
00537 for( KCal::Event::List::iterator i = eventList.begin(); i != eventList.end(); ++i )
00538 {
00539 if ( (*i)->relatedToUid() == itemAt(n)->uid() )
00540 {
00541 KDateTime kdatetimestart = (*i)->dtStart();
00542 KDateTime kdatetimeend = (*i)->dtEnd();
00543 KDateTime eventstart = KDateTime::fromString(kdatetimestart.toString().replace("Z",""));
00544 KDateTime eventend = KDateTime::fromString(kdatetimeend.toString().replace("Z",""));
00545 int duration=eventstart.secsTo( eventend )/60;
00546 itemAt(n)->addTime( duration );
00547 emit totalTimesChanged( 0, duration );
00548 kDebug(5970) << "duration is " << duration;
00549
00550 if ( itemAt(n)->sessionStartTiMe().isValid() )
00551 {
00552
00553 if ((itemAt(n)->sessionStartTiMe().secsTo( eventstart )>0) &&
00554 (itemAt(n)->sessionStartTiMe().secsTo( eventend )>0))
00555
00556 {
00557 int sessionTime=eventstart.secsTo( eventend )/60;
00558 itemAt(n)->setSessionTime( itemAt(n)->sessionTime()+sessionTime );
00559 }
00560 }
00561 else
00562
00563 {
00564 itemAt(n)->addSessionTime( duration );
00565 emit totalTimesChanged( duration, 0 );
00566 };
00567 }
00568 }
00569 }
00570 refresh();
00571 kDebug(5970) << "Leaving TaskView::reFreshTimes()";
00572 return err;
00573 }
00574
00575 void TaskView::importPlanner( const QString &fileName )
00576 {
00577 kDebug( 5970 ) << "entering importPlanner";
00578 PlannerParser *handler = new PlannerParser( this );
00579 QString lFileName = fileName;
00580 if ( lFileName.isEmpty() )
00581 lFileName = KFileDialog::getOpenFileName( QString(), QString(), 0 );
00582 QFile xmlFile( lFileName );
00583 QXmlInputSource source( &xmlFile );
00584 QXmlSimpleReader reader;
00585 reader.setContentHandler( handler );
00586 reader.parse( source );
00587 refresh();
00588 }
00589
00590 QString TaskView::report( const ReportCriteria& rc )
00591 {
00592 return d->mStorage->report( this, rc );
00593 }
00594
00595 void TaskView::exportcsvFile()
00596 {
00597 kDebug(5970) << "TaskView::exportcsvFile()";
00598
00599 CSVExportDialog dialog( ReportCriteria::CSVTotalsExport, this );
00600 if ( currentItem() && currentItem()->isRoot() )
00601 dialog.enableTasksToExportQuestion();
00602 dialog.urlExportTo->KUrlRequester::setMode(KFile::File);
00603 if ( dialog.exec() ) {
00604 QString err = d->mStorage->report( this, dialog.reportCriteria() );
00605 if ( !err.isEmpty() ) KMessageBox::error( this, i18n(err.toAscii()) );
00606 }
00607 }
00608
00609 QString TaskView::exportcsvHistory()
00610 {
00611 kDebug(5970) << "TaskView::exportcsvHistory()";
00612 QString err;
00613
00614 CSVExportDialog dialog( ReportCriteria::CSVHistoryExport, this );
00615 if ( currentItem() && currentItem()->isRoot() )
00616 dialog.enableTasksToExportQuestion();
00617 dialog.urlExportTo->KUrlRequester::setMode(KFile::File);
00618 if ( dialog.exec() ) {
00619 err = d->mStorage->report( this, dialog.reportCriteria() );
00620 }
00621 return err;
00622 }
00623
00624 long TaskView::count()
00625 {
00626 long n = 0;
00627 for (Task* t = itemAt(n); t; t=itemAt(++n)){};
00628 return n;
00629 }
00630
00631 QStringList TaskView::tasks()
00632 {
00633 QStringList result;
00634 int i=0;
00635 while ( itemAt(i) )
00636 {
00637 result << itemAt(i)->name();
00638 ++i;
00639 }
00640 return result;
00641 }
00642
00643 Task* TaskView::task( const QString& taskId )
00644 {
00645 Task* result=0;
00646 int i=-1;
00647 while ( itemAt(++i) )
00648 if ( itemAt( i ) )
00649 if ( itemAt( i )->uid() == taskId ) result=itemAt( i );
00650 return result;
00651 }
00652
00653 void TaskView::scheduleSave()
00654 {
00655 _manualSaveTimer->start( 10 );
00656 }
00657
00658 QString TaskView::save()
00659 {
00660 kDebug(5970) <<"Entering TaskView::save()";
00661 QString err=d->mStorage->save(this);
00662
00663 if (err.isNull()) emit setStatusBarText( i18n("Successfully saved file ").append( d->mStorage->icalfile() ));
00664 else
00665 if (err==QString("Could not save. Could not lock file.")) emit setStatusBarText( i18n("Could not save. Disk full ?") );
00666 else emit setStatusBarText( i18n("Could not save.") );
00667 return err;
00668 }
00669
00670 void TaskView::startCurrentTimer()
00671 {
00672 startTimerFor( currentItem() );
00673 }
00674
00675 void TaskView::startTimerFor( Task* task, const QDateTime &startTime )
00676 {
00677 kDebug(5970) << "Entering function";
00678 if (task != 0 && d->mActiveTasks.indexOf(task) == -1)
00679 {
00680 if (!task->isComplete())
00681 {
00682 if ( KTimeTrackerSettings::uniTasking() ) stopAllTimers();
00683 _idleTimeDetector->startIdleDetection();
00684 task->setRunning(true, d->mStorage, startTime);
00685 d->mActiveTasks.append(task);
00686 emit updateButtons();
00687 if ( d->mActiveTasks.count() == 1 )
00688 emit timersActive();
00689 emit tasksChanged( d->mActiveTasks );
00690 }
00691 }
00692 }
00693
00694 void TaskView::clearActiveTasks()
00695 {
00696 d->mActiveTasks.clear();
00697 }
00698
00699 void TaskView::stopAllTimers( const QDateTime &when )
00700 {
00701 kDebug(5970) << "Entering function";
00702 foreach ( Task *task, d->mActiveTasks )
00703 task->setRunning( false, d->mStorage, when );
00704
00705 _idleTimeDetector->stopIdleDetection();
00706 FocusDetectorNotifier::instance()->detach( this );
00707 d->mActiveTasks.clear();
00708 emit updateButtons();
00709 emit timersInactive();
00710 emit tasksChanged( d->mActiveTasks );
00711 }
00712
00713 void TaskView::toggleFocusTracking()
00714 {
00715 d->mFocusTrackingActive = !d->mFocusTrackingActive;
00716
00717 if ( d->mFocusTrackingActive )
00718 {
00719 FocusDetectorNotifier::instance()->attach( this );
00720 }
00721 else
00722 {
00723 stopTimerFor( d->mLastTaskWithFocus );
00724 FocusDetectorNotifier::instance()->detach( this );
00725 }
00726
00727 emit updateButtons();
00728 }
00729
00730 void TaskView::startNewSession()
00731
00732
00733
00734 {
00735 kDebug(5970) <<"Entering TaskView::startNewSession";
00736 QTreeWidgetItemIterator item( this );
00737 while ( *item )
00738 {
00739 Task * task = (Task *) *item;
00740 task->startNewSession();
00741 ++item;
00742 }
00743 kDebug(5970) << "Leaving TaskView::startNewSession";
00744 }
00745
00746 void TaskView::resetTimeForAllTasks()
00747
00748 {
00749 kDebug(5970) << "Entering TaskView::resetTimeForAllTasks";
00750 QTreeWidgetItemIterator item( this );
00751 while ( *item )
00752 {
00753 Task * task = (Task *) *item;
00754 task->resetTimes();
00755 ++item;
00756 }
00757 kDebug(5970) << "Leaving TaskView::resetTimeForAllTasks";
00758 }
00759
00760 void TaskView::stopTimerFor(Task* task)
00761 {
00762 kDebug(5970) << "Entering function";
00763 if ( task != 0 && d->mActiveTasks.indexOf(task) != -1 )
00764 {
00765 d->mActiveTasks.removeAll(task);
00766 task->setRunning(false, d->mStorage);
00767 if ( d->mActiveTasks.count() == 0 )
00768 {
00769 _idleTimeDetector->stopIdleDetection();
00770 emit timersInactive();
00771 }
00772 emit updateButtons();
00773 }
00774 emit tasksChanged( d->mActiveTasks );
00775 }
00776
00777 void TaskView::stopCurrentTimer()
00778 {
00779 stopTimerFor( currentItem() );
00780 if ( d->mFocusTrackingActive && d->mLastTaskWithFocus == currentItem() )
00781 {
00782 toggleFocusTracking();
00783 }
00784 }
00785
00786 void TaskView::minuteUpdate()
00787 {
00788 addTimeToActiveTasks(1, false);
00789 }
00790
00791 void TaskView::addTimeToActiveTasks(int minutes, bool save_data)
00792 {
00793 foreach ( Task *task, d->mActiveTasks )
00794 task->changeTime( minutes, ( save_data ? d->mStorage : 0 ) );
00795 }
00796
00797 void TaskView::newTask()
00798 {
00799 newTask(i18n("New Task"), 0);
00800 }
00801
00802 void TaskView::newTask( const QString &caption, Task *parent )
00803 {
00804 EditTaskDialog *dialog = new EditTaskDialog( this, caption, false );
00805 long total, totalDiff, session, sessionDiff;
00806 DesktopList desktopList;
00807
00808 int result = dialog->exec();
00809 if ( result == QDialog::Accepted )
00810 {
00811 QString taskName = i18n( "Unnamed Task" );
00812 if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
00813
00814 total = totalDiff = session = sessionDiff = 0;
00815 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
00816
00817
00818
00819 if ( desktopList.size() == _desktopTracker->desktopCount() )
00820 desktopList.clear();
00821
00822 QString uid = addTask( taskName, total, session, desktopList, parent );
00823 if ( uid.isNull() )
00824 {
00825 KMessageBox::error( 0, i18n(
00826 "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/ " ) );
00827 }
00828 }
00829 emit updateButtons();
00830 }
00831
00832 QString TaskView::addTask
00833 ( const QString& taskname, long total, long session,
00834 const DesktopList& desktops, Task* parent )
00835 {
00836 kDebug(5970) << "Entering function; taskname =" << taskname;
00837 setSortingEnabled(false);
00838 Task *task;
00839 if ( parent ) task = new Task( taskname, total, session, desktops, parent );
00840 else task = new Task( taskname, total, session, desktops, this );
00841
00842 task->setUid( d->mStorage->addTask( task, parent ) );
00843 QString taskuid=task->uid();
00844 if ( ! taskuid.isNull() )
00845 {
00846 _desktopTracker->registerForDesktops( task, desktops );
00847 setCurrentItem( task );
00848 task->setSelected( true );
00849 task->setPixmapProgress();
00850 save();
00851 }
00852 else
00853 {
00854 delete task;
00855 }
00856 setSortingEnabled(true);
00857 return taskuid;
00858 }
00859
00860 void TaskView::newSubTask()
00861 {
00862 Task* task = currentItem();
00863 if(!task)
00864 return;
00865 newTask(i18n("New Sub Task"), task);
00866 task->setExpanded(true);
00867 refresh();
00868 }
00869
00870 void TaskView::editTask()
00871 {
00872 kDebug(5970) <<"Entering editTask";
00873 Task *task = currentItem();
00874 if (!task)
00875 return;
00876
00877 DesktopList desktopList = task->desktops();
00878 DesktopList oldDeskTopList = desktopList;
00879 EditTaskDialog *dialog = new EditTaskDialog( this, i18n("Edit Task"), true, &desktopList );
00880 dialog->setTask( task->name(),
00881 task->time(),
00882 task->sessionTime() );
00883 int result = dialog->exec();
00884 if (result == QDialog::Accepted)
00885 {
00886 QString taskName = i18n("Unnamed Task");
00887 if (!dialog->taskName().isEmpty())
00888 {
00889 taskName = dialog->taskName();
00890 }
00891
00892 task->setName(taskName, d->mStorage);
00893
00894
00895 long total, session, totalDiff, sessionDiff;
00896 total = totalDiff = session = sessionDiff = 0;
00897 DesktopList desktopList;
00898 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00899
00900 if( totalDiff != 0 || sessionDiff != 0)
00901 task->changeTimes( sessionDiff, totalDiff, d->mStorage );
00902
00903
00904
00905 if (desktopList.size() == _desktopTracker->desktopCount())
00906 desktopList.clear();
00907
00908 if ( oldDeskTopList != desktopList )
00909 {
00910 task->setDesktopList(desktopList);
00911 _desktopTracker->registerForDesktops( task, desktopList );
00912 }
00913 emit updateButtons();
00914 }
00915 }
00916
00917 void TaskView::reinstateTask(int completion)
00918 {
00919 Task* task = currentItem();
00920 if (task == 0) {
00921 KMessageBox::information(0,i18n("No task selected."));
00922 return;
00923 }
00924
00925 if (completion<0) completion=0;
00926 if (completion<100)
00927 {
00928 task->setPercentComplete(completion, d->mStorage);
00929 task->setPixmapProgress();
00930 save();
00931 emit