33 #include "ktimetracker.h"
34 #include "storageadaptor.h"
39 #include <kemailsettings.h>
40 #include <kio/netaccess.h>
41 #include <KCalCore/Person>
44 #include <KApplication>
47 #include <KMessageBox>
48 #include <KProgressDialog>
49 #include <KSystemTimeZones>
50 #include <KTemporaryFile>
60 #include <QStringList>
61 #include <QTableWidget>
62 #include <QTextStream>
65 #include <sys/types.h>
70 using namespace KTimeTracker;
73 class timetrackerstorage::Private
78 m_fileLock =
new KLockFile(
QLatin1String(
"ktimetrackerics.lock" ) );
86 KLockFile *m_fileLock;
104 bool removedFromDirWatch =
false;
105 if ( KDirWatch::self()->contains( d->mICalFile ) ) {
106 KDirWatch::self()->removeFile( d->mICalFile );
107 removedFromDirWatch =
true;
109 kDebug(5970) <<
"Entering function";
111 KEMailSettings settings;
114 Q_ASSERT( !( lFileName.
isEmpty() ) );
117 if ( lFileName == d->mICalFile ) {
118 if ( removedFromDirWatch ) {
119 KDirWatch::self()->addFile( d->mICalFile );
126 const bool fileIsLocal = !isRemoteFile( lFileName );
131 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
140 d->mICalFile = lFileName;
141 d->mCalendar = KTTCalendar::createInstance( d->mICalFile, fileIsLocal );
144 view, SLOT(iCalFileModified()) );
145 d->mCalendar->setTimeSpec( KSystemTimeZones::local() );
146 d->mCalendar->reload();
149 KCalCore::Person::Ptr owner = d->mCalendar->owner();
150 if ( owner && owner->isEmpty() )
152 d->mCalendar->setOwner( KCalCore::Person::Ptr(
153 new KCalCore::Person( settings.getSetting( KEMailSettings::RealName ),
154 settings.getSetting( KEMailSettings::EmailAddress ) ) ) );
160 KCalCore::Todo::List todoList;
161 KCalCore::Todo::List::ConstIterator todo;
166 todoList = d->mCalendar->rawTodos();
167 kDebug(5970) <<
"timetrackerstorage::load"
168 <<
"rawTodo count (includes completed todos) ="
170 for (todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo)
179 for (todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo)
183 if ( !(*todo)->relatedTo().isEmpty() )
185 Task *newParent = map.
value( (*todo)->relatedTo() );
189 err = i18n(
"Error loading \"%1\": could not find parent (uid=%2)",
190 task->
name(), (*todo)->relatedTo() );
196 kDebug(5970) <<
"timetrackerstorage::load - loaded" << view->
count()
197 <<
"tasks from" << d->mICalFile;
200 if ( view )
buildTaskView(d->mCalendar->weakPointer(), view);
202 if ( removedFromDirWatch ) {
203 KDirWatch::self()->addFile( d->mICalFile );
212 kDebug(5970) <<
"Entering function";
213 KCalCore::Todo::List todoList;
214 KCalCore::Todo::List::ConstIterator todo;
215 todoList = d->mCalendar->rawTodos();
216 todo = todoList.constBegin();
218 bool konsolemode=
false;
219 if ( view == 0 ) konsolemode=
true;
220 while ( todo != todoList.constEnd() && ( (*todo)->uid() != uid ) ) ++todo;
221 if ( todo != todoList.constEnd() ) result =
new Task((*todo), view, konsolemode);
222 kDebug(5970) <<
"Leaving function, returning " << result;
228 kDebug(5970) <<
"Entering function";
236 kDebug(5970) <<
"Entering function";
238 KCalCore::Todo::List todoList;
239 KCalCore::Todo::List::ConstIterator todo;
258 todoList = calendar->rawTodos();
259 for ( todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo )
262 task->
setWhatsThis(0,i18n(
"The task name is what you call the task, it can be chosen freely."));
263 task->
setWhatsThis(1,i18n(
"The session time is the time since you last chose \"start new session.\""));
270 for( todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo )
274 if ( !(*todo)->relatedTo().isEmpty() )
276 Task* newParent = map.
value( (*todo)->relatedTo() );
279 err = i18n(
"Error loading \"%1\": could not find parent (uid=%2)",
281 (*todo)->relatedTo());
282 else task->
move( newParent );
288 for (
int i=0; i<view->
count(); ++i)
290 for (
int n = 0; n < runningTasks.
count(); ++n )
292 if ( runningTasks[n] == view->
itemAt(i)->
uid() )
311 kDebug(5970) <<
"Entering function";
314 d->mCalendar->close();
317 kDebug(5970) <<
"Leaving function";
322 kDebug(5970) <<
"Entering function";
323 return d->mCalendar->rawEvents();
328 kDebug(5970) <<
"Entering function";
329 return d->mCalendar->rawTodos();
334 kDebug(5970) <<
"Entering function";
335 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
336 for(KCalCore::Event::List::iterator i = eventList.begin();
337 i != eventList.end(); ++i)
339 if ( (*i)->relatedTo() == task->
uid() && !(*i)->hasEndDate() ) {
348 kDebug(5970) <<
"Entering function";
349 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
350 for(KCalCore::Event::List::iterator i = eventList.begin();
351 i != eventList.end(); ++i)
353 if ( !(*i)->hasEndDate() )
return false;
360 kDebug(5970) <<
"Entering function";
362 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
363 d->mCalendar->deleteAllEvents();
369 kDebug(5970) <<
"Entering function";
378 kDebug( 5970 ) <<
"write task" << task->
name();
379 errorString = writeTaskAsTodo( task, parents );
383 errorString = saveCalendar();
386 kDebug(5970) <<
"timetrackerstorage::save : wrote tasks to" << d->mICalFile;
388 kWarning(5970) <<
"timetrackerstorage::save :" << errorString;
396 kDebug(5970) <<
"Entering function";
398 KCalCore::Todo::Ptr todo = d->mCalendar->todo( task->
uid() );
400 todo->setRelatedTo(
QString() );
402 todo->setRelatedTo( parent->
uid() );
404 kDebug(5970) <<
"Leaving function";
410 kDebug(5970) <<
"Entering function";
412 KCalCore::Todo::Ptr todo = d->mCalendar->todo(task->
uid());
415 kDebug(5970) <<
"Could not get todo from calendar";
416 return "Could not get todo from calendar";
419 if ( !parents.
isEmpty() ) todo->setRelatedTo( parents.
top() ? parents.
top()->uid() :
QString() );
420 parents.
push( todo );
422 for (
int i = 0; i < task->
childCount(); ++i )
425 err = writeTaskAsTodo( nextTask, parents );
434 kDebug(5970) <<
"Entering function";
435 return d->mCalendar->rawTodos().isEmpty();
444 kDebug(5970) <<
"Entering function";
445 KCalCore::Todo::Ptr todo;
450 kDebug(5970) <<
"mCalendar is not set";
453 todo = KCalCore::Todo::Ptr(
new KCalCore::Todo() );
454 if ( d->mCalendar->addTodo( todo ) )
458 todo->setRelatedTo( parent->
uid() );
472 kDebug(5970) <<
"Entering function";
474 KCalCore::Todo::List todoList = d->mCalendar->rawTodos();
475 for(KCalCore::Todo::List::iterator i = todoList.begin();
476 i != todoList.end(); ++i)
478 kDebug(5970) << (*i)->uid();
479 if ( (*i)->summary() == taskname ) result << (*i)->uid();
486 kDebug(5970) <<
"Entering function";
488 KCalCore::Todo::List todoList = d->mCalendar->rawTodos();
489 for(KCalCore::Todo::List::iterator i = todoList.begin();
490 i != todoList.end(); ++i) result << (*i)->summary();
496 kDebug(5970) <<
"Entering function";
498 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
499 for(KCalCore::Event::List::iterator i = eventList.begin();
500 i != eventList.end(); ++i)
502 if ( (*i)->uid() == uid )
504 d->mCalendar->deleteEvent(*i);
512 kDebug(5970) <<
"Entering function";
514 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
515 for(KCalCore::Event::List::iterator i = eventList.begin();
516 i != eventList.end(); ++i)
518 if ( (*i)->relatedTo() == task->
uid() )
520 d->mCalendar->deleteEvent(*i);
525 KCalCore::Todo::Ptr todo = d->mCalendar->todo(task->
uid());
526 d->mCalendar->deleteTodo(todo);
535 kDebug(5970) <<
"Entering function";
537 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
538 for(KCalCore::Event::List::iterator i = eventList.begin();
539 i != eventList.end();
542 if ( (*i)->relatedTo() == taskid )
544 d->mCalendar->deleteEvent(*i);
549 KCalCore::Todo::Ptr todo = d->mCalendar->todo(taskid);
550 d->mCalendar->deleteTodo(todo);
560 kDebug(5970) <<
"Entering function";
561 KCalCore::Todo::Ptr todo = d->mCalendar->todo(task->
uid());
570 todo->setDescription(task->
comment());
577 kDebug(5970) <<
"Entering function";
581 err = exportcsvHistory( taskview, rc.
from, rc.
to, rc );
586 err = exportcsvFile( taskview, rc );
599 kDebug(5970) <<
"Entering function";
602 QString double_dquote = dquote + dquote;
603 bool to_quote =
true;
607 QString title = i18n(
"Export Progress");
608 KProgressDialog dialog( taskview, 0, title );
609 dialog.setAutoClose(
true );
610 dialog.setAllowCancel(
true );
611 dialog.progressBar()->setMaximum( 2 * taskview->
count() );
617 dialog.setInitialSize( dialogsize );
619 if ( taskview->
count() > 1 ) dialog.show();
624 while ( tasknr < taskview->count() && !dialog.wasCancelled() )
626 dialog.progressBar()->setValue( dialog.progressBar()->value() + 1 );
627 if ( tasknr % 15 == 0 ) kapp->processEvents();
628 if ( taskview->
itemAt(tasknr)->
depth() > maxdepth )
635 while ( tasknr < taskview->count() && !dialog.wasCancelled() )
637 task = taskview->
itemAt( tasknr );
638 dialog.progressBar()->setValue( dialog.progressBar()->value() + 1 );
639 if ( tasknr % 15 == 0 ) kapp->processEvents();
642 for (
int i=0; i < task->
depth(); ++i ) retval += delim;
659 retval += task->
name().
replace( dquote, double_dquote );
665 for (
int i = 0; i < maxdepth - task->
depth(); ++i ) retval += delim;
680 if ((rc.
url.isLocalFile()) || (!rc.
url.url().contains(
"/")))
683 if (filename.
isEmpty()) filename=rc.
url.url();
685 if( !f.open( QIODevice::WriteOnly ) )
687 err = i18n(
"Could not open \"%1\".", filename );
699 KTemporaryFile tmpFile;
706 if (!KIO::NetAccess::upload( tmpFile.fileName(), rc.
url, 0 )) err=
QString::fromLatin1(
"Could not upload");
718 kDebug(5970) <<
"found an event for task, event=" <<
event->uid();
719 KDateTime startTime=
event->dtStart();
720 KDateTime endTime=
event->dtEnd();
721 KDateTime NextMidNight=startTime;
722 NextMidNight.setTime(
QTime ( 0,0 ));
723 NextMidNight=NextMidNight.addDays(1);
725 KDateTime LastMidNight=KDateTime::currentLocalDateTime();
726 LastMidNight.setDate(date);
727 LastMidNight.setTime(
QTime(0,0));
728 int secsstartTillMidNight=startTime.secsTo(NextMidNight);
730 if ( (startTime.date()==date) && (event->dtEnd().date()==date) )
731 secondsToAdd=startTime.secsTo(endTime);
732 if ( (startTime.date()==date) && (endTime.date()>date) )
733 secondsToAdd=secsstartTillMidNight;
734 if ( (startTime.date()<date) && (endTime.date()==date) )
735 secondsToAdd=LastMidNight.secsTo(event->dtEnd());
736 if ( (startTime.date()<date) && (endTime.date()>date) )
748 kDebug(5970) <<
"Entering function";
755 const int intervalLength = from.
daysTo(to)+1;
764 kDebug(5970) <<
"Taskview Count: " << taskview->
count();
765 for (
int n=0; n<taskview->
count(); n++ )
768 kDebug(5970) <<
"n: " << n <<
", Task Name: " << task->
name() <<
", UID: " << task->
uid();
772 secsForUid[task->
uid()] = vector;
779 fullName += parentTask->
name();
780 parentTask = parentTask->
parent();
783 fullName = parentTask->
name() +
"->" + fullName;
784 kDebug(5970) <<
"Fullname(inside): " << fullName;
785 parentTask = parentTask->
parent();
786 kDebug(5970) <<
"Parent task: " << parentTask;
789 uidForName[fullName] = task->
uid();
791 kDebug(5970) <<
"Fullname(end): " << fullName;
794 kDebug(5970) <<
"secsForUid" << secsForUid;
795 kDebug(5970) <<
"uidForName" << uidForName;
801 kDebug(5970) <<
"Let's iterate for each date: ";
802 for (
QDate mdate=from; mdate.
daysTo(to)>=0; mdate=mdate.addDays(1) )
804 kDebug(5970) << mdate.toString();
805 KCalCore::Event::List dateEvents = d->mCalendar->rawEventsForDate(mdate);
807 for(KCalCore::Event::List::iterator i = dateEvents.begin();i != dateEvents.end(); ++i)
809 kDebug(5970) <<
"Summary: " << (*i)->summary() <<
", Related to uid: " << (*i)->relatedTo();
810 kDebug(5970) <<
"Today's seconds: " <<
todaySeconds(mdate, *i);
821 retval.
append(
"\"Task name\"");
822 for (
int i=0; i<intervalLength; ++i)
833 while (nameUid.hasNext())
836 retval.
append(
"\"" + nameUid.key() +
"\"");
837 kDebug(5970) << nameUid.key() <<
": " << nameUid.value() << endl;
839 for (
int day=0; day<intervalLength; day++)
841 kDebug(5970) <<
"Secs for day " << day <<
":" << secsForUid[nameUid.value()][day];
843 time = secsForUid[nameUid.value()][day]/60.0;
850 kDebug() <<
"Retval is \n" << retval;
857 if ((rc.
url.isLocalFile()) || (!rc.
url.url().contains(
"/")))
859 kDebug(5970) <<
"storing a local file";
861 if (filename.
isEmpty()) filename=rc.
url.url();
863 if( !f.open( QIODevice::WriteOnly ) )
865 err = i18n(
"Could not open \"%1\".", filename );
866 kDebug(5970) <<
"Could not open file";
868 kDebug() <<
"Err is " << err;
872 kDebug(5970) <<
"Writing to file: " << retval;
880 KTemporaryFile tmpFile;
881 if ( !tmpFile.open() )
890 if (!KIO::NetAccess::upload( tmpFile.fileName(), rc.
url, 0 )) err=
QString::fromLatin1(
"Could not upload");
899 kDebug(5970) <<
"Entering function; when=" << when;
900 KCalCore::Event::Ptr e;
903 d->mCalendar->addEvent(e);
909 kDebug(5970) <<
"Entering function";
910 KCalCore::Todo::List todoList;
911 KCalCore::Todo::List::ConstIterator todo;
912 todoList = d->mCalendar->rawTodos();
913 for( todo = todoList.constBegin(); todo != todoList.constEnd(); ++todo )
915 kDebug(5970) << (*todo)->uid();
916 kDebug(5970) << taskID;
917 if ( (*todo)->uid() == taskID )
919 kDebug(5970) <<
"adding event";
920 KCalCore::Event::Ptr e;
921 e = baseEvent((*todo));
922 e->setDtStart(KDateTime::currentLocalDateTime());
923 d->mCalendar->addEvent(e);
931 kDebug(5970) <<
"Entering function; when=" << when;
932 KCalCore::Event::List eventList = d->mCalendar->rawEvents();
933 for(KCalCore::Event::List::iterator i = eventList.begin();
934 i != eventList.end();
937 if ( (*i)->relatedTo() == task->
uid() )
939 kDebug(5970) <<
"found an event for task, event=" << (*i)->uid();
940 if (!(*i)->hasEndDate())
942 kDebug(5970) <<
"this event has no enddate";
943 (*i)->setDtEnd(KDateTime(when, KDateTime::Spec::LocalZone()));
947 kDebug(5970) <<
"this event has an enddate";
948 kDebug(5970) <<
"end date is " << (*i)->dtEnd();
957 kDebug(5970) <<
"Entering function; deltaSeconds=" << deltaSeconds;
958 KCalCore::Event::Ptr e;
966 e->setDtEnd(KDateTime(end, KDateTime::Spec::LocalZone()));
969 e->setCustomProperty( KGlobal::mainComponent().componentName().toUtf8(),
973 d->mCalendar->addEvent(e);
978 KCalCore::Event::Ptr timetrackerstorage::baseEvent(
const Task *task)
980 kDebug(5970) <<
"Entering function";
981 KCalCore::Event::Ptr e(
new KCalCore::Event() );
983 e->setSummary(task->
name());
986 e->setRelatedTo( task->
uid() );
989 Q_ASSERT(e->relatedTo() == task->
uid());
993 e->setDtStart(KDateTime(task->
startTime(), KDateTime::Spec::LocalZone()));
996 categories.
append(i18n(
"KTimeTracker"));
997 e->setCategories(categories);
1002 KCalCore::Event::Ptr timetrackerstorage::baseEvent(
const KCalCore::Todo::Ptr &todo)
1004 kDebug(5970) <<
"Entering function";
1005 KCalCore::Event::Ptr e(
new KCalCore::Event() );
1007 e->setSummary(todo->summary());
1010 e->setRelatedTo( todo->uid() );
1013 e->setAllDay(
false);
1014 e->setDtStart(KDateTime(todo->dtStart()));
1017 categories.
append(i18n(
"KTimeTracker"));
1018 e->setCategories(categories);
1024 long duration,
const KDateTime &start,
1025 const KDateTime &stop,
const QString &todoUid)
1035 bool timetrackerstorage::isRemoteFile(
const QString &file )
const
1037 kDebug(5970) <<
"Entering function";
1040 kDebug(5970) <<
"timetrackerstorage::isRemoteFile(" << file <<
" ) returns" << rval;
1044 QString timetrackerstorage::saveCalendar()
1046 kDebug(5970) <<
"Entering function";
1047 bool removedFromDirWatch =
false;
1048 if ( KDirWatch::self()->contains( d->mICalFile ) ) {
1049 KDirWatch::self()->removeFile( d->mICalFile );
1050 removedFromDirWatch =
true;
1054 if ( d->mCalendar ) {
1055 d->m_fileLock->lock();
1057 kDebug() <<
"mCalendar not set";
1058 return errorMessage;
1061 if ( !d->mCalendar->save() ) {
1062 errorMessage =
QString(
"Could not save. Could lock file.");
1064 d->m_fileLock->unlock();
1066 if ( removedFromDirWatch ) {
1067 KDirWatch::self()->addFile( d->mICalFile );
1070 return errorMessage;
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
QDate from
For history reports, the lower bound of the date range to report on.
int daysTo(const QDate &d) const
TaskView * taskView() const
Return task view for this task.
void closeStorage()
Close calendar and clear view.
long totalSessionTime() const
QString quote
The quote to use for text fields when outputting comma-separated reports.
QString & append(QChar ch)
void startTimer(const Task *task, const KDateTime &when=KDateTime::currentLocalDateTime())
Log the event that a timer has started for a task.
QString report(TaskView *taskview, const ReportCriteria &rc)
Output a report based on contents of ReportCriteria.
QString deleteAllEvents()
QString toString(Qt::DateFormat format) const
void append(const T &value)
QString name() const
returns the name of this task.
bool isEmpty()
Check if the iCalendar file currently loaded has any Todos in it.
void addComment(const Task *task, const QString &comment)
Log a new comment for this task.
Task * itemAt(int i)
Return the i'th item (zero-based), cast to a Task pointer.
KUrl url
For reports that write to a file, the filename to write to.
long count()
Return the total number of items in the view.
KCalCore::Todo::List rawtodos()
list of all todos
void startTimerFor(Task *task, const QDateTime &startTime=QDateTime::currentDateTime())
starts timer for task.
QString setClipBoardText(const QString &s)
Set the text of the application's clipboard.
HistoryEvent()
Needed to be used in a value list.
QStringList taskidsfromname(QString taskname)
Return a list of all task ids for taskname.
void scheduleSave()
Schedule that we should save very soon.
QString formatTime(double minutes, bool decimal)
Format time for output.
QString clipTotals(const ReportCriteria &rc)
Copy totals for current and all sub tasks to clipboard.
QString number(int n, int base)
QString delimiter
The delimiter to use when outputting comma-separated value reports.
void clearActiveTasks()
clears all active tasks.
int todaySeconds(const QDate &date, const KCalCore::Event::Ptr &event)
void append(const T &value)
QString comment() const
Retrieve the entire comment for the task.
REPORTTYPE reportType
The type of report we are running.
void refresh()
Used to refresh (e.g.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
bool removeTask(Task *task)
Remove this task from iCalendar file.
QString uid() const
Return unique iCalendar Todo ID for this task.
Stores entries from export dialog.
QHash< Key, T >::iterator insert(const Key &key, const T &value)
bool isRunning() const
return the state of a task - if it's running or not
KCalCore::Event::List rawevents()
list of all events
bool allEventsHaveEndTiMe()
Deliver if all events of the actual calendar have an endtime.
void changeTime(const Task *task, const long deltaSeconds)
Log the change in a task's time.
const T value(const Key &key) const
bool bExPortToClipBoard
True if a clipboard export is wished, not an export to a file.
int width(const QString &text, int len) const
QString & replace(int position, int n, QChar after)
bool decimalMinutes
True if the durations should be output in decimal hours.
QString setTaskParent(Task *task, Task *parent)
void stopTimer(const Task *task, const QDateTime &when=QDateTime::currentDateTime())
Log the event that the timer has stopped for this task.
int count(const T &value) const
KTimeTracker::KTTCalendar::Ptr calendar() const
Task * task(const QString &uid, TaskView *view)
Find the task with the given uid.
QString removeEvent(QString uid)
Task * parent() const
return parent Task or null in case of TaskView.
QString fromLatin1(const char *str, int size)
void move(Task *destination)
cut Task out of parent Task or the TaskView and into the destination Task
QString save(TaskView *taskview)
Save all tasks and their totals to an iCalendar file.
QDate addDays(int ndays) const
long duration()
In seconds.
QDate to
For history reports, the upper bound of the date range to report on.
QDateTime addSecs(int s) const
void setRootIsDecorated(bool show)
QString addTask(const Task *task, const Task *parent=0)
Add this task from iCalendar file.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
Container and interface for the tasks.
QString icalfile()
Return the name of the iCal file.
A class representing a task.
QString buildTaskView(const KTimeTracker::KTTCalendar::Ptr &calendar, TaskView *view)
Build up the taskview.
KCalCore::Todo::Ptr asTodo(const KCalCore::Todo::Ptr &calendar) const
Load the todo passed in with this tasks info.
QStringList taskNames() const
Return a list of all task names.
QDateTime startTime() const
Return time the task was started.
QString load(TaskView *taskview, const QString &fileName)
Load the list view with tasks read from iCalendar file.
QByteArray encodeName(const QString &fileName)