00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "timetrackerwidget.h"
00023
00024 #include <QDBusConnection>
00025 #include <QFileInfo>
00026 #include <QHBoxLayout>
00027 #include <QKeyEvent>
00028 #include <QKeySequence>
00029 #include <QMap>
00030 #include <QVBoxLayout>
00031 #include <QVector>
00032
00033 #include <KApplication>
00034 #include <KAction>
00035 #include <KActionCollection>
00036 #include <KConfig>
00037 #include <KConfigDialog>
00038 #include <KDebug>
00039 #include <KFileDialog>
00040 #include <KGlobal>
00041 #include <KIcon>
00042 #include <KLocale>
00043 #include <KMessageBox>
00044 #include <KRecentFilesAction>
00045 #include <KStandardAction>
00046 #include <KTabWidget>
00047 #include <KTemporaryFile>
00048 #include <KTreeWidgetSearchLine>
00049 #include <KUrl>
00050 #include <KIO/Job>
00051
00052 #include "edithistorydialog.h"
00053 #include "ktimetrackerutility.h"
00054 #include "ktimetracker.h"
00055 #include "mainadaptor.h"
00056 #include "reportcriteria.h"
00057 #include "task.h"
00058 #include "taskview.h"
00059 #include "version.h"
00060 #include "ui_cfgbehavior.h"
00061 #include "ui_cfgdisplay.h"
00062 #include "ui_cfgstorage.h"
00063
00064
00065 class TimetrackerWidget::Private {
00066 public:
00067 Private() :
00068 mLastView( 0 ), mRecentFilesAction( 0 ) {}
00069
00070 QWidget *mSearchLine;
00071 KTabWidget *mTabWidget;
00072 KTreeWidgetSearchLine *mSearchWidget;
00073 TaskView *mLastView;
00074 QVector<TaskView*> mIsNewVector;
00075 QMap<QString, KAction*> mActions;
00076 KRecentFilesAction *mRecentFilesAction;
00077
00078 struct ActionData {
00079 QString iconName;
00080 const char* caption;
00081 const char* slot;
00082 QString name;
00083 const char* toolTip;
00084 const char* whatsThis;
00085 };
00086 };
00087
00088
00089 TimetrackerWidget::TimetrackerWidget( QWidget *parent ) : QWidget( parent ),
00090 d( new TimetrackerWidget::Private() )
00091 {
00092 kDebug(5970) << "Entering function";
00093 new MainAdaptor( this );
00094 QDBusConnection::sessionBus().registerObject( "/KTimeTracker", this );
00095
00096 QLayout *layout = new QVBoxLayout;
00097 layout->setMargin( 0 );
00098 layout->setSpacing( 0 );
00099
00100 QLayout *innerLayout = new QHBoxLayout;
00101 d->mSearchLine = new QWidget( this );
00102 innerLayout->setMargin( KDialog::marginHint() );
00103 innerLayout->setSpacing( KDialog::spacingHint() );
00104 d->mSearchWidget = new KTreeWidgetSearchLine( d->mSearchLine );
00105 d->mSearchWidget->setClickMessage( i18n( "Search or add task" ) );
00106 d->mSearchWidget->setWhatsThis( i18n( "This is a combined field. As long as you do not type ENTER, it acts as a filter. Then, only tasks that match your input are shown. As soon as you type ENTER, your input is used as name to create a new task." ) );
00107 d->mSearchWidget->installEventFilter( this );
00108 innerLayout->addWidget( d->mSearchWidget );
00109 d->mSearchLine->setLayout( innerLayout );
00110
00111 d->mTabWidget = new KTabWidget( this );
00112 layout->addWidget( d->mSearchLine );
00113 layout->addWidget( d->mTabWidget );
00114 setLayout( layout );
00115
00116 d->mTabWidget->setFocus( Qt::OtherFocusReason );
00117
00118 connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
00119 this, SIGNAL( currentTaskViewChanged() ) );
00120 connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
00121 this, SLOT( slotCurrentChanged() ) );
00122 connect( d->mTabWidget, SIGNAL( mouseDoubleClick() ),
00123 this, SLOT( newFile() ) );
00124
00125 showSearchBar( !KTimeTrackerSettings::configPDA() );
00126 showTabBar( false );
00127 }
00128
00129 TimetrackerWidget::~TimetrackerWidget()
00130 {
00131 if ( d->mRecentFilesAction ) {
00132 d->mRecentFilesAction->saveEntries( KGlobal::config()->group( "Recent Files" ) );
00133 }
00134
00135 delete d;
00136 }
00137
00138 bool TimetrackerWidget::allEventsHaveEndTiMe()
00139 {
00140 bool result=true;
00141 TaskView *taskView;
00142 for ( int i = 0; i < d->mTabWidget->count(); ++i )
00143 {
00144 taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00145 if ( !taskView->allEventsHaveEndTiMe() ) result=false;
00146 }
00147 return result;
00148 }
00149
00150 void TimetrackerWidget::saveProperties( KConfigGroup &cfg )
00151 {
00152 cfg.writeEntry( "WindowShown", isVisible());
00153 }
00154
00155 void TimetrackerWidget::readProperties( const KConfigGroup &cfg )
00156 {
00157 if( cfg.readEntry( "WindowShown", true ))
00158 show();
00159 }
00160
00161 void TimetrackerWidget::addTaskView( const QString &fileName )
00162 {
00163 kDebug(5970) << "Entering function (fileName=" << fileName << ")";
00164 bool isNew = fileName.isEmpty();
00165 QString lFileName = fileName;
00166
00167 if ( isNew )
00168 {
00169 KTemporaryFile tempFile;
00170 tempFile.setAutoRemove( false );
00171 if ( tempFile.open() )
00172 {
00173 lFileName = tempFile.fileName();
00174 tempFile.close();
00175 }
00176 else
00177 {
00178 KMessageBox::error( this, i18n( "Cannot create new file." ) );
00179 return;
00180 }
00181 }
00182
00183 TaskView *taskView = new TaskView( this );
00184 connect( taskView, SIGNAL( contextMenuRequested( const QPoint& ) ),
00185 this, SIGNAL( contextMenuRequested( const QPoint& ) ) );
00186 connect( taskView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
00187 this, SLOT( updateTabs() ) );
00188
00189 d->mTabWidget->addTab( taskView,
00190 isNew ? KIcon( "document-save" ) : KIcon( "ktimetracker" ),
00191 isNew ? i18n( "Untitled" ) : QFileInfo( lFileName ).fileName() );
00192 d->mTabWidget->setCurrentWidget( taskView );
00193 emit setCaption( fileName );
00194 taskView->load( lFileName );
00195 d->mSearchWidget->addTreeWidget( taskView );
00196
00197 if ( isNew )
00198 {
00199 d->mIsNewVector.append( taskView );
00200 } else
00201 {
00202
00203 d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), lFileName );
00204 }
00205
00206
00207 if ( !d->mLastView )
00208 {
00209 emit currentTaskViewChanged();
00210 slotCurrentChanged();
00211 }
00212
00213 if ( d->mTabWidget->count() > 1 )
00214 {
00215 showTabBar( true );
00216 }
00217 }
00218
00219 bool TimetrackerWidget::saveCurrentTaskView()
00220 {
00221 QString fileName = KFileDialog::getSaveFileName( QString(), QString(), this );
00222 if ( !fileName.isEmpty() )
00223 {
00224 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00225 taskView->stopAllTimers();
00226 taskView->save();
00227 taskView->closeStorage();
00228
00229 QString currentFilename = taskView->storage()->icalfile();
00230 KIO::file_move( currentFilename, fileName, -1, KIO::Overwrite | KIO::HideProgressInfo );
00231 d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );
00232
00233 taskView->load( fileName );
00234 KIO::file_delete( currentFilename, KIO::HideProgressInfo );
00235
00236 d->mTabWidget->setTabIcon( d->mTabWidget->currentIndex(), KIcon( "karm" ) );
00237 d->mTabWidget->setTabText( d->mTabWidget->currentIndex(), QFileInfo( fileName ).fileName() );
00238 d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), fileName );
00239
00240 return true;
00241 }
00242
00243 return false;
00244 }
00245
00246 TaskView* TimetrackerWidget::currentTaskView()
00247 {
00248 return qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00249 }
00250
00251 Task* TimetrackerWidget::currentTask()
00252 {
00253 TaskView *taskView = 0;
00254 if ( ( taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() ) ) )
00255 {
00256 return taskView->currentItem();
00257 }
00258 else
00259 {
00260 return 0;
00261 }
00262 }
00263
00264 void TimetrackerWidget::setupActions( KActionCollection *actionCollection )
00265 {
00266 d->mActions.insert( "file_new",
00267 KStandardAction::openNew( this, SLOT( newFile() ), actionCollection ) );
00268 d->mActions[ "file_new" ]->setIcon( KIcon( "tab-new" ) );
00269
00270 d->mActions.insert ("file_open",
00271 KStandardAction::open( this, SLOT( openFile() ), actionCollection ) );
00272
00273 d->mRecentFilesAction = KStandardAction::openRecent(
00274 this, SLOT( openFile( const KUrl & ) ), this );
00275 actionCollection->addAction( d->mRecentFilesAction->objectName(),
00276 d->mRecentFilesAction );
00277 d->mRecentFilesAction->loadEntries( KGlobal::config()->group( "Recent Files" ) );
00278
00279 d->mActions.insert ("file_save",
00280 KStandardAction::save( this, SLOT( saveFile() ), actionCollection ) );
00281 d->mActions.insert ("file_close",
00282 KStandardAction::close( this, SLOT( closeFile() ), actionCollection ) );
00283 d->mActions.insert ("file_quit",
00284 KStandardAction::quit( this, SLOT( quit() ), actionCollection ) );
00285 d->mActions.insert ("configure_ktimetracker",
00286 KStandardAction::preferences( this, SLOT( showSettingsDialog() ),
00287 actionCollection ) );
00288
00289 Private::ActionData actions[] = {
00290 { QString(), I18N_NOOP("Start &New Session"), SLOT( startNewSession() ),
00291 "start_new_session", I18N_NOOP("Starts a new session"), I18N_NOOP("This will reset the "
00292 "session time to 0 for all tasks, to start a new session, without "
00293 "affecting the totals.") },
00294 { "view-history", I18N_NOOP("Edit History..."), SLOT( editHistory() ), "edit_history",
00295 I18N_NOOP("Edits history of all tasks of the current document"), I18N_NOOP("A window will "
00296 "be opened where you can change start and stop times of tasks or add a "
00297 "comment to them.") },
00298 { QString(), I18N_NOOP("&Reset All Times"), SLOT( resetAllTimes() ),
00299 "reset_all_times", I18N_NOOP("Resets all times"), I18N_NOOP("This will reset the session "
00300 "and total time to 0 for all tasks, to restart from scratch.") },
00301 { "media-playback-start", I18N_NOOP("&Start"), SLOT( startCurrentTimer() ), "start",
00302 I18N_NOOP("Starts timing for selected task"), I18N_NOOP("This will start timing for the "
00303 "selected task.\nIt is even possible to time several tasks "
00304 "simultanously.\n\nYou may also start timing of tasks by double clicking "
00305 "the left mouse button on a given task. This will, however, stop timing "
00306 "of other tasks.") },
00307 { "media-playback-stop", I18N_NOOP("S&top"), SLOT( stopCurrentTimer() ), "stop",
00308 I18N_NOOP("Stops timing of the selected task"), I18N_NOOP("Stops timing of the selected task") },
00309 { QString(), I18N_NOOP("Stop &All Timers"), SLOT( stopAllTimers() ), "stopAll",
00310 I18N_NOOP("Stops all of the active timers"), I18N_NOOP("Stops all of the active timers") },
00311 { QString(), I18N_NOOP("Track Active Applications"), SLOT( focusTracking() ),
00312 "focustracking", I18N_NOOP("Auto-creates and updates tasks when the focus of the "
00313 "current window has changed"), I18N_NOOP("If the focus of a window changes for the "
00314 "first time when this action is enabled, a new task will be created "
00315 "with the title of the window as its name and will be started. If there "
00316 "already exists such an task it will be started.") },
00317 { "document-new", I18N_NOOP("&New Task..."), SLOT( newTask() ), "new_task", I18N_NOOP("Creates "
00318 "new top level task"), I18N_NOOP("This will create a new top level task.") },
00319 { "subtask-new-ktimetracker", I18N_NOOP("New &Subtask..."), SLOT( newSubTask() ),
00320 "new_sub_task", I18N_NOOP("Creates a new subtask to the current selected task"),
00321 I18N_NOOP("This will create a new subtask to the current selected task.") },
00322 { "edit-delete", I18N_NOOP("&Delete"), SLOT( deleteTask() ), "delete_task", I18N_NOOP("Deletes "
00323 "selected task"), I18N_NOOP("This will delete the selected task(s) and all "
00324 "subtasks.") },
00325 { "document-properties", I18N_NOOP("&Edit..."), SLOT( editTask() ), "edit_task",
00326 I18N_NOOP("Edits name or times for selected task"), I18N_NOOP("This will bring up a dialog "
00327 "box where you may edit the parameters for the selected task.") },
00328 { QString(), I18N_NOOP("&Mark as Complete"), SLOT( markTaskAsComplete() ),
00329 "mark_as_complete", "", "" },
00330 { QString(), I18N_NOOP("&Mark as Incomplete"), SLOT( markTaskAsIncomplete() ),
00331 "mark_as_incomplete", "", "" },
00332 { QString(), I18N_NOOP("&Export Times..."), SLOT( exportcsvFile() ), "export_times",
00333 "", "" },
00334 { QString(), I18N_NOOP("Export &History..."), SLOT( exportcsvHistory() ),
00335 "export_history", "", "" },
00336 { QString(), I18N_NOOP("Import Tasks From &Planner..."), SLOT( importPlanner() ),
00337 "import_planner", "", "" },
00338 { QString(), I18N_NOOP("Show Searchbar"), SLOT( slotSearchBar() ), "searchbar",
00339 "", "" }
00340 };
00341
00342 for ( unsigned int i = 0;
00343 i < ( sizeof( actions ) / sizeof( Private::ActionData ) ); ++i )
00344 {
00345 Private::ActionData actionData = actions[i];
00346 KAction *action;
00347 if ( actionData.iconName.isEmpty() )
00348 {
00349 action = new KAction( i18n( actionData.caption ), this );
00350 } else
00351 {
00352 action = new KAction( KIcon( actionData.iconName ),
00353 i18n( actionData.caption ), this );
00354 }
00355
00356 actionCollection->addAction( actionData.name, action );
00357 connect( action, SIGNAL( triggered( bool ) ), actionData.slot );
00358 action->setToolTip( i18n( actionData.toolTip ) );
00359 action->setWhatsThis( i18n( actionData.whatsThis ) );
00360
00361 d->mActions.insert( actionData.name, action );
00362 }
00363
00364
00365 d->mActions[ "stopAll" ]->setShortcut( QKeySequence( Qt::Key_Escape ) );
00366 d->mActions[ "new_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_T ) );
00367 d->mActions[ "new_sub_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_N ) );
00368 d->mActions[ "delete_task" ]->setShortcut( QKeySequence( Qt::Key_Delete ) );
00369 d->mActions[ "edit_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_E ) );
00370 d->mActions[ "mark_as_complete" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
00371 d->mActions[ "mark_as_incomplete" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
00372
00373 d->mActions[ "mark_as_complete" ]->setIcon( UserIcon( "task-complete.xpm" ) );
00374 d->mActions[ "mark_as_incomplete" ]->setIcon( UserIcon( "task-incomplete.xpm" ) );
00375
00376 d->mActions[ "focustracking" ]->setCheckable( true );
00377 d->mActions[ "searchbar" ]->setCheckable( true );
00378
00379 d->mActions[ "searchbar" ]->setChecked( KTimeTrackerSettings::self()->showSearchBar() );
00380
00381 connect( this, SIGNAL( currentTaskChanged() ),
00382 this, SLOT( slotUpdateButtons() ) );
00383 connect( this, SIGNAL( currentTaskViewChanged() ),
00384 this, SLOT( slotUpdateButtons() ) );
00385 connect( this, SIGNAL( updateButtons() ),
00386 this, SLOT( slotUpdateButtons() ) );
00387
00388 slotUpdateButtons();
00389 }
00390
00391 KAction* TimetrackerWidget::action( const QString &name ) const
00392 {
00393 return d->mActions.value( name );
00394 }
00395
00396 void TimetrackerWidget::newFile()
00397 {
00398 addTaskView();
00399 }
00400
00401 void TimetrackerWidget::openFile( const QString &fileName )
00402 {
00403 QString newFileName = fileName;
00404 if ( newFileName.isEmpty() )
00405 {
00406 newFileName = KFileDialog::getOpenFileName( QString(), QString(),
00407 this );
00408 if ( newFileName.isEmpty() )
00409 {
00410 return;
00411 }
00412 }
00413
00414 if ( d->mRecentFilesAction )
00415 {
00416 d->mRecentFilesAction->addUrl( newFileName );
00417 }
00418 addTaskView( newFileName );
00419 }
00420
00421 void TimetrackerWidget::openFile( const KUrl &fileName )
00422 {
00423 openFile( fileName.path() );
00424 }
00425
00426 bool TimetrackerWidget::closeFile()
00427 {
00428 kDebug(5970) << "Entering TimetrackerWidget::closeFile";
00429 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00430
00431
00432 if ( d->mIsNewVector.contains( taskView ) )
00433 {
00434 QString message = i18n( "This document has not been saved yet. Do you want to save it?" );
00435 QString caption = i18n( "Untitled" );
00436
00437 int result = KMessageBox::questionYesNoCancel( this, message, caption );
00438
00439 if ( result == KMessageBox::Cancel )
00440 {
00441 return false;
00442 }
00443
00444 if ( result == KMessageBox::Yes )
00445 {
00446 if ( !saveCurrentTaskView() )
00447 {
00448 return false;
00449 }
00450 }
00451 else
00452 {
00453 d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );
00454 }
00455 }
00456
00457 taskView->save();
00458 taskView->closeStorage();
00459
00460 d->mTabWidget->removeTab( d->mTabWidget->currentIndex() );
00461 d->mSearchWidget->removeTreeWidget( taskView );
00462
00463
00464
00465
00466 if ( d->mTabWidget->count() == 0 )
00467 {
00468 emit currentTaskViewChanged();
00469 emit setCaption( QString() );
00470 slotCurrentChanged();
00471 }
00472
00473
00474 if ( d->mTabWidget->count() < 2 )
00475 {
00476 showTabBar( false );
00477 }
00478
00479 delete taskView;
00480 return true;
00481 }
00482
00483 void TimetrackerWidget::saveFile()
00484 {
00485 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00486
00487
00488 if ( d->mIsNewVector.contains( taskView ) )
00489 {
00490 saveCurrentTaskView();
00491 }
00492
00493 taskView->save();
00494
00495
00496
00497 }
00498
00499 void TimetrackerWidget::showTabBar( bool visible )
00500 {
00501 d->mTabWidget->setTabBarHidden( !visible );
00502 }
00503
00504 void TimetrackerWidget::reconfigureFiles()
00505 {
00506 kDebug(5970) << "Entering function";
00507 TaskView *taskView;
00508 for ( int i = 0; i < d->mTabWidget->count(); ++i )
00509 {
00510 taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00511
00512 taskView->reconfigure();
00513 }
00514 }
00515
00516 void TimetrackerWidget::showSearchBar( bool visible )
00517 {
00518 d->mSearchLine->setVisible( visible );
00519 }
00520
00521 bool TimetrackerWidget::closeAllFiles()
00522 {
00523 kDebug(5970) << "Entering TimetrackerWidget::closeAllFiles";
00524 while ( d->mTabWidget->count() > 0 )
00525 {
00526 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( 0 ) );
00527 d->mTabWidget->setCurrentWidget( taskView );
00528 if ( !( closeFile() ) )
00529 return false;
00530 }
00531 return true;
00532 }
00533
00534 void TimetrackerWidget::slotCurrentChanged()
00535 {
00536 kDebug() << "entering KTimetrackerWidget::slotCurrentChanged";
00537
00538 if ( d->mLastView )
00539 {
00540 disconnect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ) );
00541 disconnect( d->mLastView, SIGNAL( reSetTimes() ) );
00542 disconnect( d->mLastView, SIGNAL( itemSelectionChanged() ) );
00543 disconnect( d->mLastView, SIGNAL( updateButtons() ) );
00544 disconnect( d->mLastView, SIGNAL( setStatusBarText( QString ) ) );
00545 disconnect( d->mLastView, SIGNAL( timersActive() ) );
00546 disconnect( d->mLastView, SIGNAL( timersInactive() ) );
00547 disconnect( d->mLastView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
00548 this, SIGNAL( tasksChanged( const QList< Task* > & ) ) );
00549 }
00550
00551 d->mLastView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00552
00553 if ( d->mLastView )
00554 {
00555 connect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ),
00556 this, SIGNAL( totalTimesChanged( long, long ) ) );
00557 connect( d->mLastView, SIGNAL( reSetTimes() ),
00558 this, SIGNAL( reSetTimes() ) );
00559 connect( d->mLastView, SIGNAL( itemSelectionChanged() ),
00560 this, SIGNAL( currentTaskChanged() ) );
00561 connect( d->mLastView, SIGNAL( updateButtons() ),
00562 this, SIGNAL( updateButtons() ) );
00563 connect( d->mLastView, SIGNAL( setStatusBarText( QString ) ),
00564 this, SIGNAL( statusBarTextChangeRequested( const QString & ) ) );
00565 connect( d->mLastView, SIGNAL( timersActive() ),
00566 this, SIGNAL( timersActive() ) );
00567 connect( d->mLastView, SIGNAL( timersInactive() ),
00568 this, SIGNAL( timersInactive() ) );
00569 connect( d->mLastView, SIGNAL( tasksChanged( QList< Task* > ) ),
00570 this, SIGNAL( tasksChanged( const QList< Task* > &) ) );
00571 emit setCaption( d->mLastView->storage()->icalfile() );
00572 }
00573
00574 d->mSearchWidget->setEnabled( d->mLastView );
00575 }
00576
00577 void TimetrackerWidget::updateTabs()
00578 {
00579 kDebug(5970) << "Entering function";
00580 TaskView *taskView;
00581 for ( int i = 0; i < d->mTabWidget->count(); ++i )
00582 {
00583 taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00584
00585 if ( taskView->activeTasks().count() == 0 )
00586 {
00587 d->mTabWidget->setTabTextColor( i, palette().color( QPalette::Foreground ) );
00588 }
00589 else
00590 {
00591 d->mTabWidget->setTabTextColor( i, Qt::darkGreen );
00592 }
00593 }
00594 kDebug(5970) << "Leaving function";
00595 }
00596
00597 bool TimetrackerWidget::eventFilter( QObject *obj, QEvent *event )
00598 {
00599 if ( obj == d->mSearchWidget )
00600 {
00601 if ( event->type() == QEvent::KeyPress )
00602 {
00603 QKeyEvent *keyEvent = static_cast< QKeyEvent* >( event );
00604 if ( keyEvent->key() == Qt::Key_Enter ||
00605 keyEvent->key() == Qt::Key_Return )
00606 {
00607 if ( !d->mSearchWidget->displayText().isEmpty() ) slotAddTask( d->mSearchWidget->displayText() );
00608 return true;
00609 }
00610 }
00611 }
00612
00613 return QObject::eventFilter( obj, event );
00614 }
00615
00616 void TimetrackerWidget::slotAddTask( const QString &taskName )
00617 {
00618 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00619
00620 taskView->addTask( taskName, 0, 0, DesktopList(), 0 );
00621
00622 d->mSearchWidget->clear();
00623 d->mTabWidget->setFocus( Qt::OtherFocusReason );
00624 }
00625
00626 void TimetrackerWidget::slotUpdateButtons()
00627 {
00628 kDebug(5970) << "Entering function";
00629 Task *item = currentTask();
00630
00631 d->mActions[ "start" ]->setEnabled( item && !item->isRunning() &&
00632 !item->isComplete() );
00633 d->mActions[ "stop" ]->setEnabled( item && item->isRunning() );
00634 d->mActions[ "delete_task" ]->setEnabled( item );
00635 d->mActions[ "edit_task" ]->setEnabled( item );
00636 d->mActions[ "mark_as_complete" ]->setEnabled( item && !item->isComplete() );
00637 d->mActions[ "mark_as_incomplete" ]->setEnabled( item && item->isComplete() );
00638
00639 d->mActions[ "new_task" ]->setEnabled( currentTaskView() );
00640 d->mActions[ "new_sub_task" ]->setEnabled( currentTaskView() && currentTaskView()->count() );
00641 d->mActions[ "focustracking" ]->setEnabled( currentTaskView() );
00642 d->mActions[ "focustracking" ]->setChecked( currentTaskView() &&
00643 currentTaskView()->isFocusTrackingActive() );
00644 d->mActions[ "start_new_session" ]->setEnabled( currentTaskView() );
00645 d->mActions[ "edit_history" ]->setEnabled( currentTaskView() );
00646 d->mActions[ "reset_all_times" ]->setEnabled( currentTaskView() );
00647 d->mActions[ "export_times" ]->setEnabled( currentTaskView() );
00648 d->mActions[ "export_history" ]->setEnabled( currentTaskView() );
00649 d->mActions[ "import_planner" ]->setEnabled( currentTaskView() );
00650 d->mActions[ "file_save" ]->setEnabled( currentTaskView() );
00651 d->mActions[ "file_close" ]->setEnabled( currentTaskView() );
00652 kDebug(5970) << "Leaving function";
00653 }
00654
00655 void TimetrackerWidget::showSettingsDialog()
00656 {
00657 kDebug(5970) << "Entering function";
00658
00659
00660
00661 window()->show();
00662
00663 KConfigDialog *dialog = new KConfigDialog(
00664 this, "settings", KTimeTrackerSettings::self() );
00665
00666 Ui::BehaviorPage *behaviorUi = new Ui::BehaviorPage;
00667 QWidget *behaviorPage = new QWidget;
00668 behaviorUi->setupUi( behaviorPage );
00669 dialog->addPage( behaviorPage, i18n( "Behavior" ), "preferences-other" );
00670
00671 Ui::DisplayPage *displayUi = new Ui::DisplayPage;
00672 QWidget *displayPage = new QWidget;
00673 displayUi->setupUi( displayPage );
00674 dialog->addPage( displayPage,
00675 i18nc( "settings page for customizing user interface",
00676 "Appearance" ),
00677 "preferences-desktop-theme" );
00678
00679 Ui::StoragePage *storageUi = new Ui::StoragePage;
00680 QWidget *storagePage = new QWidget;
00681 storageUi->setupUi( storagePage );
00682 dialog->addPage( storagePage, i18n( "Storage" ), "system-file-manager" );
00683
00684 dialog->exec();
00685 showSearchBar( !KTimeTrackerSettings::configPDA() );
00686 reconfigureFiles();
00687 }
00688
00689
00690 void TimetrackerWidget::startCurrentTimer()
00691 {
00692 if ( d->mTabWidget->currentWidget() ) {
00693 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->startCurrentTimer();
00694 }
00695 }
00696
00697 void TimetrackerWidget::stopCurrentTimer()
00698 {
00699 if ( d->mTabWidget->currentWidget() ) {
00700 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopCurrentTimer();
00701 }
00702 }
00703
00704 void TimetrackerWidget::stopAllTimers( const QDateTime &when )
00705 {
00706 if ( d->mTabWidget->currentWidget() ) {
00707 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopAllTimers( when );
00708 }
00709 }
00710
00711 void TimetrackerWidget::newTask()
00712 {
00713 if ( d->mTabWidget->currentWidget() ) {
00714 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newTask();
00715 }
00716 }
00717
00718 void TimetrackerWidget::newSubTask()
00719 {
00720 if ( d->mTabWidget->currentWidget() ) {
00721 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newSubTask();
00722 }
00723 }
00724
00725 void TimetrackerWidget::editTask()
00726 {
00727 if ( d->mTabWidget->currentWidget() ) {
00728 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->editTask();
00729 }
00730 }
00731
00732 void TimetrackerWidget::deleteTask()
00733 {
00734 if ( d->mTabWidget->currentWidget() ) {
00735 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->deleteTask();
00736 }
00737 }
00738
00739 void TimetrackerWidget::markTaskAsComplete()
00740 {
00741 if ( d->mTabWidget->currentWidget() ) {
00742 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsComplete();
00743 }
00744 }
00745
00746 void TimetrackerWidget::markTaskAsIncomplete()
00747 {
00748 if ( d->mTabWidget->currentWidget() ) {
00749 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsIncomplete();
00750 }
00751 }
00752
00753 void TimetrackerWidget::exportcsvFile()
00754 {
00755 if ( d->mTabWidget->currentWidget() ) {
00756 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->exportcsvFile();
00757 }
00758 }
00759
00760 void TimetrackerWidget::exportcsvHistory()
00761 {
00762 if ( d->mTabWidget->currentWidget() ) {
00763 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->exportcsvHistory();
00764 }
00765 }
00766
00767 void TimetrackerWidget::importPlanner( const QString &fileName )
00768 {
00769 if ( d->mTabWidget->currentWidget() ) {
00770 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->importPlanner( fileName );
00771 }
00772 }
00773
00774 void TimetrackerWidget::startNewSession()
00775 {
00776 if ( d->mTabWidget->currentWidget() ) {
00777 qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->startNewSession();
00778 }
00779 }
00780
00781 void TimetrackerWidget::editHistory()
00782 {
00783 if ( d->mTabWidget->currentWidget() )
00784 {
00785 EditHistoryDialog *dlg = new EditHistoryDialog( qobject_cast< TaskView* >( d->mTabWidget->currentWidget() ) );
00786 if (currentTaskView()->storage()->rawevents().count()!=0) dlg->exec();
00787 else KMessageBox::information(0, i18nc("@info in message box", "There is no history yet. Start and stop a task and you will have an entry in your history."));
00788 }
00789 }
00790
00791 void TimetrackerWidget::resetAllTimes()
00792 {
00793 if ( d->mTabWidget->currentWidget() ) {
00794 if ( KMessageBox::warningContinueCancel( this,
00795 i18n( "Do you really want to reset the time to zero for all tasks?" ),
00796 i18n( "Confirmation Required" ), KGuiItem( i18n( "Reset All Times" ) ) ) == KMessageBox::Continue )
00797 currentTaskView()->resetTimeForAllTasks();
00798 }
00799 }
00800
00801 void TimetrackerWidget::focusTracking()
00802 {
00803 if ( d->mTabWidget->currentWidget() ) {
00804 currentTaskView()->toggleFocusTracking();
00805 d->mActions[ "focustracking" ]->setChecked(
00806 currentTaskView()->isFocusTrackingActive() );
00807 }
00808 }
00809
00810 void TimetrackerWidget::slotSearchBar()
00811 {
00812 bool currentVisible = KTimeTrackerSettings::self()->showSearchBar();
00813 KTimeTrackerSettings::self()->setShowSearchBar( !currentVisible );
00814 d->mActions[ "searchbar" ]->setChecked( !currentVisible );
00815 showSearchBar( !currentVisible );
00816 }
00817
00818
00819
00820 QString TimetrackerWidget::version() const
00821 {
00822 return KTIMETRACKER_VERSION;
00823 }
00824
00825 QStringList TimetrackerWidget::taskIdsFromName( const QString &taskName ) const
00826 {
00827 QStringList result;
00828
00829 for ( int i = 0; i < d->mTabWidget->count(); ++i) {
00830 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00831
00832 if ( !taskView ) continue;
00833
00834 QTreeWidgetItemIterator it( taskView );
00835 while ( *it ) {
00836 Task *task = static_cast< Task* >( *it );
00837 if ( task && task->name() == taskName ) {
00838 result << task->uid();
00839 }
00840 ++it;
00841 }
00842 }
00843
00844 return result;
00845 }
00846
00847 void TimetrackerWidget::addTask( const QString &taskName )
00848 {
00849 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00850
00851 if ( taskView )
00852 {
00853 taskView->addTask( taskName, 0, 0, DesktopList(), 0 );
00854 }
00855 }
00856
00857 void TimetrackerWidget::addSubTask( const QString& taskName, const QString &taskId )
00858 {
00859 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
00860
00861 if ( taskView )
00862 {
00863 taskView->addTask( taskName, 0, 0, DesktopList(), taskView->task( taskId) );
00864 taskView->refresh();
00865 }
00866 }
00867
00868 void TimetrackerWidget::deleteTask( const QString &taskId )
00869 {
00870 for ( int i = 0; i < d->mTabWidget->count(); ++i)
00871 {
00872 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00873
00874 if ( !taskView ) continue;
00875
00876 QTreeWidgetItemIterator it( taskView );
00877 while ( *it )
00878 {
00879 Task *task = static_cast< Task* >( *it );
00880 if ( task && task->uid() == taskId )
00881 {
00882 taskView->deleteTaskBatch( task );
00883 }
00884 ++it;
00885 }
00886 }
00887 }
00888
00889 void TimetrackerWidget::setPercentComplete( const QString &taskId, int percent )
00890 {
00891 for ( int i = 0; i < d->mTabWidget->count(); ++i) {
00892 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00893
00894 if ( !taskView ) continue;
00895
00896 QTreeWidgetItemIterator it( taskView );
00897 while ( *it ) {
00898 Task *task = static_cast< Task* >( *it );
00899 if ( task && task->uid() == taskId ) {
00900 task->setPercentComplete( percent, taskView->storage() );
00901 }
00902 ++it;
00903 }
00904 }
00905 }
00906
00907 int TimetrackerWidget::bookTime( const QString &taskId, const QString &dateTime, int minutes )
00908 {
00909 QDate startDate;
00910 QTime startTime;
00911 QDateTime startDateTime;
00912 Task *task = 0, *t = 0;
00913
00914 if ( minutes <= 0 ) return KTIMETRACKER_ERR_INVALID_DURATION;
00915
00916
00917 for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
00918 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00919
00920 if ( !taskView ) continue;
00921
00922 QTreeWidgetItemIterator it( taskView );
00923 while ( *it ) {
00924 t = static_cast< Task* >( *it );
00925 if ( t && t->uid() == taskId ) {
00926 task = t;
00927 break;
00928 }
00929 ++it;
00930 }
00931
00932 if ( task ) break;
00933 }
00934
00935 if ( !task ) return KTIMETRACKER_ERR_UID_NOT_FOUND;
00936
00937
00938 startDate = QDate::fromString( dateTime, Qt::ISODate );
00939
00940 if ( dateTime.length() > 10 ) {
00941 startTime = QTime::fromString( dateTime, Qt::ISODate );
00942 } else startTime = QTime( 12, 0 );
00943
00944 if ( startDate.isValid() && startTime.isValid() ) {
00945 startDateTime = QDateTime( startDate, startTime );
00946 } else return KTIMETRACKER_ERR_INVALID_DATE;
00947
00948
00949 task->changeTotalTimes( task->sessionTime() + minutes,
00950 task->totalTime() + minutes );
00951 if ( !( task->taskView()->storage()->bookTime( task,
00952 startDateTime,
00953 minutes * 60 ) ) )
00954 return KTIMETRACKER_ERR_GENERIC_SAVE_FAILED;
00955
00956 return 0;
00957 }
00958
00959 QString TimetrackerWidget::error( int errorCode ) const
00960 {
00961 switch ( errorCode ) {
00962 case KTIMETRACKER_ERR_GENERIC_SAVE_FAILED:
00963 return i18n( "Save failed, most likely because the file could not be locked." );
00964 case KTIMETRACKER_ERR_COULD_NOT_MODIFY_RESOURCE:
00965 return i18n( "Could not modify calendar resource." );
00966 case KTIMETRACKER_ERR_MEMORY_EXHAUSTED:
00967 return i18n( "Out of memory--could not create object." );
00968 case KTIMETRACKER_ERR_UID_NOT_FOUND:
00969 return i18n( "UID not found." );
00970 case KTIMETRACKER_ERR_INVALID_DATE:
00971 return i18n( "Invalidate date--format is YYYY-MM-DD." );
00972 case KTIMETRACKER_ERR_INVALID_TIME:
00973 return i18n( "Invalid time--format is YYYY-MM-DDTHH:MM:SS." );
00974 case KTIMETRACKER_ERR_INVALID_DURATION:
00975 return i18n( "Invalid task duration--must be greater than zero." );
00976 default:
00977 return i18n( "Invalid error number: %1", errorCode );
00978 }
00979 }
00980
00981 int TimetrackerWidget::totalMinutesForTaskId( const QString &taskId ) const
00982 {
00983 for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
00984 TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );
00985
00986 if ( !taskView ) continue;
00987
00988 QTreeWidgetItemIterator it( taskView );
00989 while ( *it ) {
00990 Task *task =