mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
990 lines
31 KiB
C++
990 lines
31 KiB
C++
/*
|
||
* Copyright (C) 2007 by Mathias Soeken <msoeken@tzi.de>
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License along
|
||
* with this program; if not, write to the
|
||
* Free Software Foundation, Inc.
|
||
* 51 Franklin Street, Fifth Floor
|
||
* Boston, MA 02110-1301 USA.
|
||
*
|
||
*/
|
||
|
||
// TODO: what is the sense of tasksChanged()?
|
||
|
||
#include "timetrackerwidget.h"
|
||
#include "ktimetrackerconfigdialog.h"
|
||
|
||
#include <QDBusConnection>
|
||
#include <QFileInfo>
|
||
#include <QHBoxLayout>
|
||
#include <QKeyEvent>
|
||
#include <QKeySequence>
|
||
#include <QMap>
|
||
#include <QVBoxLayout>
|
||
#include <QVector>
|
||
|
||
#include <KApplication>
|
||
#include <KAction>
|
||
#include <KActionCollection>
|
||
#include <KConfig>
|
||
#include <KConfigDialog>
|
||
#include <KDebug>
|
||
#include <KFileDialog>
|
||
#include <KGlobal>
|
||
#include <KIcon>
|
||
#include <KLocale>
|
||
#include <KMessageBox>
|
||
#include <KRecentFilesAction>
|
||
#include <KStandardAction>
|
||
#include <KTabWidget>
|
||
#include <KTemporaryFile>
|
||
#include <KTreeWidgetSearchLine>
|
||
#include <KUrl>
|
||
#include <KIO/Job>
|
||
|
||
#include "historydialog.h"
|
||
#include "idletimedetector.h"
|
||
#include "ktimetrackerutility.h"
|
||
#include "ktimetracker.h"
|
||
#include "mainadaptor.h"
|
||
#include "reportcriteria.h"
|
||
#include "task.h"
|
||
#include "taskview.h"
|
||
#include "kdepim-version.h"
|
||
|
||
|
||
//@cond PRIVATE
|
||
class TimetrackerWidget::Private
|
||
{
|
||
public:
|
||
Private() :
|
||
mTaskView( 0 ) {}
|
||
|
||
QWidget *mSearchLine;
|
||
KTreeWidgetSearchLine *mSearchWidget;
|
||
TaskView *mTaskView;
|
||
QMap<QString, KAction*> mActions;
|
||
|
||
struct ActionData
|
||
{
|
||
QString iconName;
|
||
const char* caption;
|
||
const char* slot;
|
||
QString name;
|
||
const char* toolTip;
|
||
const char* whatsThis;
|
||
};
|
||
};
|
||
//@endcond
|
||
|
||
TimetrackerWidget::TimetrackerWidget( QWidget *parent ) : QWidget( parent ),
|
||
d( new TimetrackerWidget::Private() )
|
||
{
|
||
kDebug(5970) << "Entering function";
|
||
new MainAdaptor( this );
|
||
QDBusConnection::sessionBus().registerObject( "/KTimeTracker", this );
|
||
|
||
QLayout *layout = new QVBoxLayout;
|
||
layout->setMargin( 0 );
|
||
layout->setSpacing( 0 );
|
||
|
||
QLayout *innerLayout = new QHBoxLayout;
|
||
d->mSearchLine = new QWidget( this );
|
||
innerLayout->setMargin( KDialog::marginHint() );
|
||
innerLayout->setSpacing( KDialog::spacingHint() );
|
||
d->mSearchWidget = new KTreeWidgetSearchLine( d->mSearchLine );
|
||
d->mSearchWidget->setClickMessage( i18n( "Search or add task" ) );
|
||
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." ) );
|
||
d->mSearchWidget->installEventFilter( this );
|
||
innerLayout->addWidget( d->mSearchWidget );
|
||
d->mSearchLine->setLayout( innerLayout );
|
||
|
||
d->mTaskView = new TaskView( this );
|
||
layout->addWidget( d->mSearchLine );
|
||
layout->addWidget( d->mTaskView );
|
||
setLayout( layout );
|
||
|
||
showSearchBar( !KTimeTrackerSettings::configPDA() && KTimeTrackerSettings::showSearchBar() );
|
||
}
|
||
|
||
TimetrackerWidget::~TimetrackerWidget()
|
||
{
|
||
delete d;
|
||
}
|
||
|
||
bool TimetrackerWidget::allEventsHaveEndTiMe()
|
||
{
|
||
return currentTaskView()->allEventsHaveEndTiMe();
|
||
}
|
||
|
||
int TimetrackerWidget::focusSearchBar()
|
||
{
|
||
kDebug(5970) << "Entering function";
|
||
if ( d->mSearchWidget->isVisible() ) d->mSearchWidget->setFocus();
|
||
return 0;
|
||
}
|
||
|
||
void TimetrackerWidget::addTaskView( const QString &fileName )
|
||
{
|
||
kDebug(5970) << "Entering function (fileName=" << fileName << ")";
|
||
bool isNew = fileName.isEmpty();
|
||
QString lFileName = fileName;
|
||
|
||
if ( isNew )
|
||
{
|
||
KTemporaryFile tempFile;
|
||
tempFile.setAutoRemove( false );
|
||
if ( tempFile.open() )
|
||
{
|
||
lFileName = tempFile.fileName();
|
||
tempFile.close();
|
||
}
|
||
else
|
||
{
|
||
KMessageBox::error( this, i18n( "Cannot create new file." ) );
|
||
return;
|
||
}
|
||
}
|
||
|
||
TaskView *taskView = d->mTaskView;
|
||
|
||
connect( taskView, SIGNAL(contextMenuRequested(QPoint)),
|
||
this, SIGNAL(contextMenuRequested(QPoint)) );
|
||
connect( taskView, SIGNAL(timersActive()),
|
||
this, SIGNAL(timersActive()) );
|
||
connect( taskView, SIGNAL(timersInactive()),
|
||
this, SIGNAL(timersInactive()) );
|
||
connect( taskView, SIGNAL(tasksChanged(QList<Task*>)),
|
||
this, SIGNAL(tasksChanged(QList<Task*>)));
|
||
|
||
emit setCaption( fileName );
|
||
taskView->load( lFileName );
|
||
d->mSearchWidget->addTreeWidget( taskView );
|
||
|
||
// When adding the first tab currentChanged is not emitted, so...
|
||
if ( !d->mTaskView )
|
||
{
|
||
emit currentTaskViewChanged();
|
||
slotCurrentChanged();
|
||
}
|
||
}
|
||
|
||
TaskView* TimetrackerWidget::currentTaskView() const
|
||
{
|
||
return qobject_cast< TaskView* >( d->mTaskView );
|
||
}
|
||
|
||
Task* TimetrackerWidget::currentTask()
|
||
{
|
||
TaskView *taskView = 0;
|
||
if ( ( taskView = currentTaskView() ) )
|
||
{
|
||
return taskView->currentItem();
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::setupActions( KActionCollection *actionCollection )
|
||
{
|
||
d->mActions.insert ("file_open",
|
||
KStandardAction::open( this, SLOT(openFile()), actionCollection ) );
|
||
d->mActions.insert ("file_save",
|
||
KStandardAction::save( this, SLOT(saveFile()), actionCollection ) );
|
||
d->mActions.insert ("file_quit",
|
||
KStandardAction::quit( this, SLOT(quit()), actionCollection ) );
|
||
d->mActions.insert ("configure_ktimetracker",
|
||
KStandardAction::preferences( this, SLOT(showSettingsDialog()),
|
||
actionCollection ) );
|
||
|
||
Private::ActionData actions[] =
|
||
{
|
||
{ QString(), I18N_NOOP("Start &New Session"), SLOT(startNewSession()),
|
||
"start_new_session", I18N_NOOP("Starts a new session"), I18N_NOOP("This will reset the "
|
||
"session time to 0 for all tasks, to start a new session, without "
|
||
"affecting the totals.")
|
||
},
|
||
{ "view-history", I18N_NOOP("Edit History..."), SLOT(editHistory()), "edit_history",
|
||
I18N_NOOP("Edits history of all tasks of the current document"), I18N_NOOP("A window will "
|
||
"be opened where you can change start and stop times of tasks or add a "
|
||
"comment to them.")
|
||
},
|
||
{ QString(), I18N_NOOP("&Reset All Times"), SLOT(resetAllTimes()),
|
||
"reset_all_times", I18N_NOOP("Resets all times"), I18N_NOOP("This will reset the session "
|
||
"and total time to 0 for all tasks, to restart from scratch.")
|
||
},
|
||
{ "media-playback-start", I18N_NOOP("&Start"), SLOT(startCurrentTimer()), "start",
|
||
I18N_NOOP("Starts timing for selected task"), I18N_NOOP("This will start timing for the "
|
||
"selected task.\nIt is even possible to time several tasks "
|
||
"simultanously.\n\nYou may also start timing of tasks by double clicking "
|
||
"the left mouse button on a given task. This will, however, stop timing "
|
||
"of other tasks.")
|
||
},
|
||
{ "media-playback-stop", I18N_NOOP("S&top"), SLOT(stopCurrentTimer()), "stop",
|
||
I18N_NOOP("Stops timing of the selected task"), I18N_NOOP("Stops timing of the selected task")
|
||
},
|
||
{ QString(), I18N_NOOP("Focus on Searchbar"), SLOT(focusSearchBar()), "focusSearchBar",
|
||
I18N_NOOP("Sets the focus on the searchbar"), I18N_NOOP("Sets the focus on the searchbar")
|
||
},
|
||
{ QString(), I18N_NOOP("Stop &All Timers"), SLOT(stopAllTimers()), "stopAll",
|
||
I18N_NOOP("Stops all of the active timers"), I18N_NOOP("Stops all of the active timers")
|
||
},
|
||
{ QString(), I18N_NOOP("Track Active Applications"), SLOT(focusTracking()),
|
||
"focustracking", I18N_NOOP("Auto-creates and updates tasks when the focus of the "
|
||
"current window has changed"), I18N_NOOP("If the focus of a window changes for the "
|
||
"first time when this action is enabled, a new task will be created "
|
||
"with the title of the window as its name and will be started. If there "
|
||
"already exists such an task it will be started.")
|
||
},
|
||
// in the following element,
|
||
// document-new is the icon name, e.g. for the toolbar, new_task is how the action is
|
||
// called in the ktimetrackerui.rc file, rest should be obvious
|
||
{ "document-new", I18N_NOOP("&New Task..."), SLOT(newTask()), "new_task", I18N_NOOP("Creates "
|
||
"new top level task"), I18N_NOOP("This will create a new top level task.")
|
||
},
|
||
{ "subtask-new-ktimetracker", I18N_NOOP("New &Subtask..."), SLOT(newSubTask()),
|
||
"new_sub_task", I18N_NOOP("Creates a new subtask to the current selected task"),
|
||
I18N_NOOP("This will create a new subtask to the current selected task.")
|
||
},
|
||
{ "edit-delete", I18N_NOOP("&Delete"), SLOT(deleteTask()), "delete_task", I18N_NOOP("Deletes "
|
||
"selected task"), I18N_NOOP("This will delete the selected task(s) and all "
|
||
"subtasks.")
|
||
},
|
||
{ "document-properties", I18N_NOOP("&Edit..."), SLOT(editTask()), "edit_task",
|
||
I18N_NOOP("Edits name or times for selected task"), I18N_NOOP("This will bring up a dialog "
|
||
"box where you may edit the parameters for the selected task.")
|
||
},
|
||
{ QString(), I18N_NOOP("&Mark as Complete"), SLOT(markTaskAsComplete()),
|
||
"mark_as_complete", "", ""
|
||
},
|
||
{ QString(), I18N_NOOP("&Mark as Incomplete"), SLOT(markTaskAsIncomplete()),
|
||
"mark_as_incomplete", "", ""
|
||
},
|
||
{ QString(), I18N_NOOP("&Export Times..."), SLOT(exportcsvFile()), "export_times",
|
||
"", ""
|
||
},
|
||
{ QString(), I18N_NOOP("Export &History..."), SLOT(exportcsvHistory()),
|
||
"export_history", "", ""
|
||
},
|
||
{ QString(), I18N_NOOP("Import Tasks From &Planner..."), SLOT(importPlanner()),
|
||
"import_planner", "", ""
|
||
},
|
||
{ QString(), I18N_NOOP("Show Searchbar"), SLOT(slotSearchBar()), "searchbar",
|
||
"", ""
|
||
}
|
||
};
|
||
|
||
for ( unsigned int i = 0; i < ( sizeof( actions ) / sizeof( Private::ActionData ) ); ++i )
|
||
{
|
||
Private::ActionData actionData = actions[i];
|
||
KAction *action;
|
||
if ( actionData.iconName.isEmpty() )
|
||
{
|
||
action = new KAction( i18n( actionData.caption ), this );
|
||
}
|
||
else
|
||
{
|
||
action = new KAction( KIcon( actionData.iconName ),
|
||
i18n( actionData.caption ), this );
|
||
}
|
||
|
||
actionCollection->addAction( actionData.name, action );
|
||
connect( action, SIGNAL(triggered(bool)), actionData.slot );
|
||
action->setToolTip( i18n( actionData.toolTip ) );
|
||
action->setWhatsThis( i18n( actionData.whatsThis ) );
|
||
|
||
d->mActions.insert( actionData.name, action );
|
||
}
|
||
|
||
// custom shortcuts
|
||
d->mActions[ "start" ]->setShortcut( QKeySequence( Qt::Key_G) );
|
||
d->mActions[ "stopAll" ]->setShortcut( QKeySequence( Qt::Key_Escape ) );
|
||
d->mActions[ "new_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_T ) );
|
||
d->mActions[ "focusSearchBar" ]->setShortcut( QKeySequence( Qt::Key_S ) );
|
||
d->mActions[ "new_sub_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_N ) );
|
||
d->mActions[ "delete_task" ]->setShortcut( QKeySequence( Qt::Key_Delete ) );
|
||
d->mActions[ "edit_task" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_E ) );
|
||
d->mActions[ "mark_as_complete" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
|
||
d->mActions[ "mark_as_incomplete" ]->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
|
||
|
||
d->mActions[ "mark_as_complete" ]->setIcon( UserIcon( "task-complete.xpm" ) );
|
||
d->mActions[ "mark_as_incomplete" ]->setIcon( UserIcon( "task-incomplete.xpm" ) );
|
||
|
||
d->mActions[ "focustracking" ]->setCheckable( true );
|
||
d->mActions[ "searchbar" ]->setCheckable( true );
|
||
|
||
d->mActions[ "searchbar" ]->setChecked( KTimeTrackerSettings::self()->showSearchBar() );
|
||
|
||
connect( this, SIGNAL(currentTaskChanged()),
|
||
this, SLOT(slotUpdateButtons()) );
|
||
connect( this, SIGNAL(currentTaskViewChanged()),
|
||
this, SLOT(slotUpdateButtons()) );
|
||
connect( this, SIGNAL(updateButtons()),
|
||
this, SLOT(slotUpdateButtons()) );
|
||
}
|
||
|
||
KAction* TimetrackerWidget::action( const QString &name ) const
|
||
{
|
||
return d->mActions.value( name );
|
||
}
|
||
|
||
void TimetrackerWidget::openFile( const QString &fileName )
|
||
{
|
||
kDebug(5970) << "Entering function, fileName is " << fileName;
|
||
QString newFileName = fileName;
|
||
if ( newFileName.isEmpty() )
|
||
{
|
||
newFileName = KFileDialog::getOpenFileName( QString(), QString(), this );
|
||
if ( newFileName.isEmpty() )
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
addTaskView( newFileName );
|
||
}
|
||
|
||
void TimetrackerWidget::openFile( const KUrl &fileName )
|
||
{
|
||
openFile( fileName.toLocalFile() );
|
||
}
|
||
|
||
bool TimetrackerWidget::closeFile()
|
||
{
|
||
kDebug(5970) << "Entering TimetrackerWidget::closeFile";
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( taskView )
|
||
{
|
||
taskView->save();
|
||
taskView->closeStorage();
|
||
}
|
||
|
||
d->mSearchWidget->removeTreeWidget( taskView );
|
||
|
||
emit currentTaskViewChanged();
|
||
emit setCaption( QString() );
|
||
slotCurrentChanged();
|
||
|
||
delete taskView; // removeTab does not delete its widget.
|
||
d->mTaskView=0;
|
||
return true;
|
||
}
|
||
|
||
void TimetrackerWidget::saveFile()
|
||
{
|
||
currentTaskView()->save();
|
||
}
|
||
|
||
void TimetrackerWidget::showSearchBar( bool visible )
|
||
{
|
||
d->mSearchLine->setVisible( visible );
|
||
}
|
||
|
||
bool TimetrackerWidget::closeAllFiles()
|
||
{
|
||
kDebug(5970) << "Entering TimetrackerWidget::closeAllFiles";
|
||
bool err = true;
|
||
if (d->mTaskView)
|
||
{
|
||
d->mTaskView->stopAllTimers();
|
||
err=closeFile();
|
||
}
|
||
return err;
|
||
}
|
||
|
||
void TimetrackerWidget::slotCurrentChanged()
|
||
{
|
||
kDebug() << "entering KTimetrackerWidget::slotCurrentChanged";
|
||
|
||
if ( d->mTaskView )
|
||
{
|
||
disconnect( d->mTaskView, SIGNAL(totalTimesChanged(long,long)) );
|
||
disconnect( d->mTaskView, SIGNAL(reSetTimes()) );
|
||
disconnect( d->mTaskView, SIGNAL(itemSelectionChanged()) );
|
||
disconnect( d->mTaskView, SIGNAL(updateButtons()) );
|
||
disconnect( d->mTaskView, SIGNAL(setStatusBarText(QString)) );
|
||
disconnect( d->mTaskView, SIGNAL(timersActive()) );
|
||
disconnect( d->mTaskView, SIGNAL(timersInactive()) );
|
||
disconnect( d->mTaskView, SIGNAL(tasksChanged(QList<Task*>)),
|
||
this, SIGNAL(tasksChanged(QList<Task*>)) );
|
||
|
||
connect( d->mTaskView, SIGNAL(totalTimesChanged(long,long)),
|
||
this, SIGNAL(totalTimesChanged(long,long)) );
|
||
connect( d->mTaskView, SIGNAL(reSetTimes()),
|
||
this, SIGNAL(reSetTimes()) );
|
||
connect( d->mTaskView, SIGNAL(itemSelectionChanged()),
|
||
this, SIGNAL(currentTaskChanged()) );
|
||
connect( d->mTaskView, SIGNAL(updateButtons()),
|
||
this, SIGNAL(updateButtons()) );
|
||
connect( d->mTaskView, SIGNAL(setStatusBarText(QString)), // FIXME signature
|
||
this, SIGNAL(statusBarTextChangeRequested(QString)) );
|
||
connect( d->mTaskView, SIGNAL(timersActive()),
|
||
this, SIGNAL(timersActive()) );
|
||
connect( d->mTaskView, SIGNAL(timersInactive()),
|
||
this, SIGNAL(timersInactive()) );
|
||
connect( d->mTaskView, SIGNAL(tasksChanged(QList<Task*>)), // FIXME signature
|
||
this, SIGNAL(tasksChanged(QList<Task*>)) );
|
||
emit setCaption( d->mTaskView->storage()->icalfile() );
|
||
}
|
||
d->mSearchWidget->setEnabled( d->mTaskView );
|
||
}
|
||
|
||
|
||
bool TimetrackerWidget::eventFilter( QObject *obj, QEvent *event )
|
||
{
|
||
if ( obj == d->mSearchWidget )
|
||
{
|
||
if ( event->type() == QEvent::KeyPress )
|
||
{
|
||
QKeyEvent *keyEvent = static_cast< QKeyEvent* >( event );
|
||
if ( keyEvent->key() == Qt::Key_Enter ||
|
||
keyEvent->key() == Qt::Key_Return )
|
||
{
|
||
if ( !d->mSearchWidget->displayText().isEmpty() ) slotAddTask( d->mSearchWidget->displayText() );
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return QObject::eventFilter( obj, event );
|
||
}
|
||
|
||
void TimetrackerWidget::slotAddTask( const QString &taskName )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
taskView->addTask( taskName, QString(), 0, 0, DesktopList(), 0 );
|
||
|
||
d->mSearchWidget->clear();
|
||
}
|
||
|
||
void TimetrackerWidget::slotUpdateButtons()
|
||
{
|
||
kDebug(5970) << "Entering function";
|
||
Task *item = currentTask();
|
||
|
||
d->mActions[ "start" ]->setEnabled( item && !item->isRunning() &&
|
||
!item->isComplete() );
|
||
d->mActions[ "stop" ]->setEnabled( item && item->isRunning() );
|
||
d->mActions[ "delete_task" ]->setEnabled( item );
|
||
d->mActions[ "edit_task" ]->setEnabled( item );
|
||
d->mActions[ "mark_as_complete" ]->setEnabled( item && !item->isComplete() );
|
||
d->mActions[ "mark_as_incomplete" ]->setEnabled( item && item->isComplete() );
|
||
|
||
d->mActions[ "new_task" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "new_sub_task" ]->setEnabled( currentTaskView() && currentTaskView()->count() );
|
||
d->mActions[ "focustracking" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "focustracking" ]->setChecked( currentTaskView() &&
|
||
currentTaskView()->isFocusTrackingActive() );
|
||
d->mActions[ "start_new_session" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "edit_history" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "reset_all_times" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "export_times" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "export_history" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "import_planner" ]->setEnabled( currentTaskView() );
|
||
d->mActions[ "file_save" ]->setEnabled( currentTaskView() );
|
||
kDebug(5970) << "Leaving function";
|
||
}
|
||
|
||
void TimetrackerWidget::showSettingsDialog()
|
||
{
|
||
kDebug(5970) << "Entering function";
|
||
/* show main window b/c if this method was started from tray icon and the window
|
||
is not visible the application quits after accepting the settings dialog.
|
||
*/
|
||
window()->show();
|
||
KTimeTrackerConfigDialog *dialog=new KTimeTrackerConfigDialog(i18n( "Settings" ), this);
|
||
dialog->exec();
|
||
delete dialog;
|
||
KTimeTrackerSettings::self()->readConfig();
|
||
|
||
showSearchBar(!KTimeTrackerSettings::configPDA() && KTimeTrackerSettings::showSearchBar());
|
||
currentTaskView()->reconfigure();
|
||
}
|
||
|
||
//BEGIN wrapper slots
|
||
void TimetrackerWidget::startCurrentTimer()
|
||
{
|
||
currentTaskView()->startCurrentTimer();
|
||
}
|
||
|
||
void TimetrackerWidget::stopCurrentTimer()
|
||
{
|
||
currentTaskView()->stopCurrentTimer();
|
||
}
|
||
|
||
void TimetrackerWidget::stopAllTimers( const QDateTime &when )
|
||
{
|
||
currentTaskView()->stopAllTimers(when);
|
||
}
|
||
|
||
void TimetrackerWidget::newTask()
|
||
{
|
||
currentTaskView()->newTask();
|
||
}
|
||
|
||
void TimetrackerWidget::newSubTask()
|
||
{
|
||
currentTaskView()->newSubTask();
|
||
}
|
||
|
||
void TimetrackerWidget::editTask()
|
||
{
|
||
currentTaskView()->editTask();
|
||
}
|
||
|
||
void TimetrackerWidget::deleteTask()
|
||
{
|
||
currentTaskView()->deleteTask();
|
||
}
|
||
|
||
void TimetrackerWidget::markTaskAsComplete()
|
||
{
|
||
currentTaskView()->markTaskAsComplete();
|
||
}
|
||
|
||
void TimetrackerWidget::markTaskAsIncomplete()
|
||
{
|
||
currentTaskView()->markTaskAsIncomplete();
|
||
}
|
||
|
||
void TimetrackerWidget::exportcsvFile()
|
||
{
|
||
currentTaskView()->exportcsvFile();
|
||
}
|
||
|
||
void TimetrackerWidget::exportcsvHistory()
|
||
{
|
||
currentTaskView()->exportcsvHistory();
|
||
}
|
||
|
||
void TimetrackerWidget::importPlanner( const QString &fileName )
|
||
{
|
||
currentTaskView()->importPlanner(fileName);
|
||
}
|
||
|
||
void TimetrackerWidget::startNewSession()
|
||
{
|
||
currentTaskView()->startNewSession();
|
||
}
|
||
|
||
void TimetrackerWidget::editHistory()
|
||
{
|
||
// historydialog is the new historydialog, but the EditHiStoryDiaLog exists as well.
|
||
// historydialog can be edited with qtcreator and qtdesigner, EditHiStoryDiaLog cannot.
|
||
if ( currentTaskView() )
|
||
{
|
||
historydialog *dlg = new historydialog( currentTaskView() );
|
||
if (currentTaskView()->storage()->rawevents().count()!=0) dlg->exec();
|
||
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."));
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::resetAllTimes()
|
||
{
|
||
if ( currentTaskView() )
|
||
{
|
||
if ( KMessageBox::warningContinueCancel( this,
|
||
i18n( "Do you really want to reset the time to zero for all tasks? This will delete the entire history." ),
|
||
i18n( "Confirmation Required" ), KGuiItem( i18n( "Reset All Times" ) ) ) == KMessageBox::Continue )
|
||
currentTaskView()->resetTimeForAllTasks();
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::focusTracking()
|
||
{
|
||
currentTaskView()->toggleFocusTracking();
|
||
d->mActions["focustracking"]->setChecked(currentTaskView()->isFocusTrackingActive());
|
||
}
|
||
|
||
void TimetrackerWidget::slotSearchBar()
|
||
{
|
||
bool currentVisible = KTimeTrackerSettings::self()->showSearchBar();
|
||
KTimeTrackerSettings::self()->setShowSearchBar( !currentVisible );
|
||
d->mActions[ "searchbar" ]->setChecked( !currentVisible );
|
||
showSearchBar( !currentVisible );
|
||
}
|
||
//END
|
||
|
||
/** \defgroup dbus slots ‘‘dbus slots’’ */
|
||
/* @{ */
|
||
QString TimetrackerWidget::version() const
|
||
{
|
||
return KDEPIM_VERSION;
|
||
}
|
||
|
||
QStringList TimetrackerWidget::taskIdsFromName( const QString &taskName ) const
|
||
{
|
||
QStringList result;
|
||
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return result;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->name() == taskName )
|
||
{
|
||
result << task->uid();
|
||
}
|
||
++it;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
void TimetrackerWidget::addTask( const QString &taskName )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( taskView )
|
||
{
|
||
taskView->addTask( taskName, QString(), 0, 0, DesktopList(), 0 );
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::addSubTask( const QString& taskName, const QString &taskId )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( taskView )
|
||
{
|
||
taskView->addTask( taskName, QString(), 0, 0, DesktopList(), taskView->task( taskId) );
|
||
taskView->refresh();
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::deleteTask( const QString &taskId )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( !taskView ) return;
|
||
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
taskView->deleteTaskBatch( task );
|
||
}
|
||
++it;
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::setPercentComplete( const QString &taskId, int percent )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( !taskView ) return;
|
||
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
task->setPercentComplete( percent, taskView->storage() );
|
||
}
|
||
++it;
|
||
}
|
||
}
|
||
|
||
int TimetrackerWidget::changeTime( const QString &taskId, int minutes )
|
||
{
|
||
int result=0;
|
||
QDate startDate;
|
||
QTime startTime;
|
||
QDateTime startDateTime;
|
||
Task *task = 0, *t = 0;
|
||
|
||
TaskView *taskView;
|
||
|
||
if ( minutes <= 0 ) return KTIMETRACKER_ERR_INVALID_DURATION;
|
||
|
||
// Find task
|
||
taskView = currentTaskView();
|
||
if ( taskView ) return KTIMETRACKER_ERR_UID_NOT_FOUND; //FIXME: it mimics the behaviour with the for loop, but I am not sure semantics were right. Maybe a new error code must be defined?
|
||
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it ) {
|
||
t = static_cast< Task* >( *it );
|
||
if ( t && t->uid() == taskId ) {
|
||
task = t;
|
||
break;
|
||
}
|
||
++it;
|
||
}
|
||
|
||
if ( !task ) result=KTIMETRACKER_ERR_UID_NOT_FOUND;
|
||
else task->changeTime(minutes, task->taskView()->storage());
|
||
return result;
|
||
}
|
||
|
||
QString TimetrackerWidget::error( int errorCode ) const
|
||
{
|
||
switch ( errorCode )
|
||
{
|
||
case KTIMETRACKER_ERR_GENERIC_SAVE_FAILED:
|
||
return i18n( "Save failed, most likely because the file could not be locked." );
|
||
case KTIMETRACKER_ERR_COULD_NOT_MODIFY_RESOURCE:
|
||
return i18n( "Could not modify calendar resource." );
|
||
case KTIMETRACKER_ERR_MEMORY_EXHAUSTED:
|
||
return i18n( "Out of memory--could not create object." );
|
||
case KTIMETRACKER_ERR_UID_NOT_FOUND:
|
||
return i18n( "UID not found." );
|
||
case KTIMETRACKER_ERR_INVALID_DATE:
|
||
return i18n( "Invalidate date--format is YYYY-MM-DD." );
|
||
case KTIMETRACKER_ERR_INVALID_TIME:
|
||
return i18n( "Invalid time--format is YYYY-MM-DDTHH:MM:SS." );
|
||
case KTIMETRACKER_ERR_INVALID_DURATION:
|
||
return i18n( "Invalid task duration--must be greater than zero." );
|
||
default:
|
||
return i18n( "Invalid error number: %1", errorCode );
|
||
}
|
||
}
|
||
|
||
bool TimetrackerWidget::isIdleDetectionPossible() const
|
||
{
|
||
bool result;
|
||
IdleTimeDetector *idletimedetector1=new IdleTimeDetector(50);
|
||
result=idletimedetector1->isIdleDetectionPossible();
|
||
delete idletimedetector1;
|
||
return result;
|
||
}
|
||
|
||
int TimetrackerWidget::totalMinutesForTaskId( const QString &taskId ) const
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return -1;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
return task->totalTime();
|
||
}
|
||
++it;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
void TimetrackerWidget::startTimerFor( const QString &taskId )
|
||
{
|
||
kDebug();
|
||
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
taskView->startTimerFor( task );
|
||
return;
|
||
}
|
||
++it;
|
||
}
|
||
}
|
||
|
||
bool TimetrackerWidget::startTimerForTaskName( const QString &taskName )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return false;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->name() == taskName )
|
||
{
|
||
taskView->startTimerFor( task );
|
||
return true;
|
||
}
|
||
++it;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
bool TimetrackerWidget::stopTimerForTaskName( const QString &taskName )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return false;
|
||
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
|
||
if ( task && task->name() == taskName )
|
||
{
|
||
taskView->stopTimerFor( task );
|
||
return true;
|
||
}
|
||
++it;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
void TimetrackerWidget::stopTimerFor( const QString &taskId )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
taskView->stopTimerFor( task );
|
||
return;
|
||
}
|
||
++it;
|
||
}
|
||
}
|
||
|
||
void TimetrackerWidget::stopAllTimersDBUS()
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if (taskView) taskView->stopAllTimers();
|
||
}
|
||
|
||
QString TimetrackerWidget::exportCSVFile( const QString &filename,
|
||
const QString &from,
|
||
const QString &to, int type,
|
||
bool decimalMinutes,
|
||
bool allTasks,
|
||
const QString &delimiter,
|
||
const QString "e )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
|
||
if ( !taskView ) return "";
|
||
ReportCriteria rc;
|
||
rc.url = filename;
|
||
rc.from = QDate::fromString( from );
|
||
if ( rc.from.isNull() )
|
||
rc.from = QDate::fromString( from, Qt::ISODate );
|
||
rc.to = QDate::fromString( to );
|
||
if ( rc.to.isNull() )
|
||
rc.to = QDate::fromString( to, Qt::ISODate );
|
||
rc.reportType = ( ReportCriteria::REPORTTYPE )type;
|
||
rc.decimalMinutes = decimalMinutes;
|
||
rc.allTasks = allTasks;
|
||
rc.delimiter = delimiter;
|
||
rc.quote = quote;
|
||
|
||
return taskView->report( rc );
|
||
}
|
||
|
||
void TimetrackerWidget::importPlannerFile( const QString &filename )
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return;
|
||
taskView->importPlanner( filename );
|
||
}
|
||
|
||
bool TimetrackerWidget::isActive( const QString &taskId ) const
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return false;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
|
||
if ( task && task->uid() == taskId )
|
||
{
|
||
return task->isRunning();
|
||
}
|
||
++it;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool TimetrackerWidget::isTaskNameActive( const QString &taskName ) const
|
||
{
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return false;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
Task *task = static_cast< Task* >( *it );
|
||
if ( task && task->name() == taskName )
|
||
{
|
||
return task->isRunning();
|
||
}
|
||
++it;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
QStringList TimetrackerWidget::tasks() const
|
||
{
|
||
QStringList result;
|
||
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return result;
|
||
QTreeWidgetItemIterator it( taskView );
|
||
while ( *it )
|
||
{
|
||
result << static_cast< Task* >( *it )->name();
|
||
++it;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
QStringList TimetrackerWidget::activeTasks() const
|
||
{
|
||
QStringList result;
|
||
TaskView *taskView = currentTaskView();
|
||
if ( !taskView ) return result;
|
||
for ( int j = 0; j < taskView->count(); ++j )
|
||
{
|
||
if ( taskView->itemAt( j )->isRunning() )
|
||
{
|
||
result << taskView->itemAt( j )->name();
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
void TimetrackerWidget::saveAll()
|
||
{
|
||
currentTaskView()->save();
|
||
}
|
||
|
||
bool TimetrackerWidget::event ( QEvent * event ) // inherited from QWidget
|
||
{
|
||
if (event->type()==QEvent::QueryWhatsThis)
|
||
{
|
||
if ( d->mTaskView->count() == 0 )
|
||
setWhatsThis( i18n("This is ktimetracker, KDE's program to help you track your time. Best, start with creating your first task - enter it into the field where you see \"search or add task\".") );
|
||
else setWhatsThis( i18n("You have already created a task. You can now start and stop timing") );
|
||
}
|
||
return QWidget::event(event);
|
||
}
|
||
|
||
void TimetrackerWidget::quit()
|
||
{
|
||
kDebug(5970) << "Entering TimetrackerWidget::quit";
|
||
if ( closeAllFiles() )
|
||
{
|
||
kapp->quit();
|
||
}
|
||
}
|
||
// END of dbus slots group
|
||
/* @} */
|