diff --git a/client/helper.cpp b/client/helper.cpp index e5e390c..aee6481 100644 --- a/client/helper.cpp +++ b/client/helper.cpp @@ -79,6 +79,12 @@ date date::fromTimestamp(time_t timestamp, int options) return r; } +date date::today() +{ + date r = date::fromTimestamp(time(nullptr), To_LocalTime); + return r; +} + int date::daysInMonth(int y, int m) { switch (m) @@ -103,6 +109,26 @@ int date::daysInMonth(int y, int m) } } +bool date::operator < (const date& rhs) +{ + return std::tie(mYear, mMonth, mDay) < std::tie(rhs.mYear, rhs.mMonth, rhs.mDay); +} + +bool date::operator > (const date& rhs) +{ + return std::tie(mYear, mMonth, mDay) > std::tie(rhs.mYear, rhs.mMonth, rhs.mDay); +} + +bool date::operator == (const date& rhs) +{ + return std::tie(mYear, mMonth, mDay) == std::tie(rhs.mYear, rhs.mMonth, rhs.mDay); +} + +bool date::operator >= (const date& rhs) +{ + return std::tie(mYear, mMonth, mDay) >= std::tie(rhs.mYear, rhs.mMonth, rhs.mDay); +} + std::string chrono::secondsToDisplay(int seconds, bool showSeconds) { @@ -125,6 +151,7 @@ std::string chrono::timeToStr(time_t timestamp) return buf; } +/* std::string chrono::timeToLocalStr(time_t timestamp) { char buf[128]; @@ -132,6 +159,7 @@ std::string chrono::timeToLocalStr(time_t timestamp) strftime(buf, sizeof buf, "%FT%TZ", &t); return buf; } +*/ time_t chrono::strToTime(const std::string& s) { diff --git a/client/helper.h b/client/helper.h index e009fbd..fdca824 100644 --- a/client/helper.h +++ b/client/helper.h @@ -33,19 +33,19 @@ namespace helper static date today(); static date fromTm(struct tm& t); static int daysInMonth(int y, int m); + + bool operator < (const date& rhs); + bool operator > (const date& rhs); + bool operator == (const date& rhs); + bool operator >= (const date& rhs); }; - bool operator < (const date& lhs, const date& rhs); - bool operator > (const date& lhs, const date& rhs); - bool operator == (const date& lhs, const date& rhs); - bool operator >= (const date& lhs, const date& rhs); class chrono { public: static std::string secondsToDisplay(int seconds, bool showSeconds); static std::string timeToStr(time_t timestamp); - static std::string timeToLocalStr(time_t timestamp); static time_t strToTime(const std::string& s); static struct tm localtime(time_t timestamp); static int daysInMonth(int m, int y); diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 77a207c..7e085bc 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -892,7 +892,7 @@ void MainWindow::startTrackingRecent() } } -void MainWindow::stopTracking(TrackingStopReason reason, const QDateTime& currentUtc) +void MainWindow::stopTracking(TrackingStopReason reason, time_t current_utc) { // Check if false call if (!mCurrentTask) @@ -907,7 +907,7 @@ void MainWindow::stopTracking(TrackingStopReason reason, const QDateTime& curren // Tell current task to stop - mCurrentTask->timeline()->flush(true /* save to DB */, currentUtc); + mCurrentTask->timeline()->flush(true /* save to DB */, current_utc); mCurrentTask->timeline()->stop(false /* do not update timeline - it is done in the previous line */); // Save stopped task name @@ -1301,7 +1301,7 @@ void MainWindow::updateTrayIcon(TrayShowMessage flag) { bool showSeconds = mSettings->data()[KEY_SHOW_SECONDS].toBool(); int spentSecondsToday = mCurrentTask->timeline()->today(); - QString timeString = helper::chrono::secondsToDisplay(spentSecondsToday, showSeconds); + QString timeString = QString::fromStdString(helper::chrono::secondsToDisplay(spentSecondsToday, showSeconds)); tooltip = tr("Litt is tracking ") + mCurrentTask->title() + ".\n" + tr("Time spent today for this task is ") + timeString; } @@ -1445,7 +1445,7 @@ void MainWindow::checkForUpdates() void MainWindow::systemSleep() { //qDebug() << "System goes to sleep"; - stopTracking(TSR_Automatic, QDateTime::currentDateTimeUtc()); + stopTracking(TSR_Automatic, QDateTime::currentDateTimeUtc().toTime_t()); } void MainWindow::systemResume() @@ -1472,7 +1472,7 @@ void MainWindow::changeTimeTrackableFlag(bool trackable) // Stop task if it is marked as non tracking and it is running now if (!trackable && mCurrentTask == t) - stopTracking(TSR_Manual, QDateTime::currentDateTimeUtc()); + stopTracking(TSR_Manual, time(nullptr)); // Update UI handleTrackableState(t); @@ -1517,11 +1517,11 @@ void MainWindow::findRequested() } //ui->mFindEdit->setVisible(false); - QTextCursor c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, 0); + QTextCursor c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, nullptr); if (c.isNull()) { mFindStartIndex = 0; - c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, 0); + c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, nullptr); } if (!c.isNull()) { @@ -1595,7 +1595,7 @@ void MainWindow::continueOnIdle() void MainWindow::breakOnIdle(const QDateTime& stopTime) { // Stop tracking - stopTracking(TSR_Manual, stopTime); + stopTracking(TSR_Manual, stopTime.toUTC().toTime_t()); showTimeForSelectedTask(); } diff --git a/client/mainwindow.h b/client/mainwindow.h index 475ce38..952c27a 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -160,7 +160,7 @@ public slots: void startTracking(); void startTrackingRecent(); - void stopTracking(TrackingStopReason reason, const QDateTime& currentUtc = QDateTime::currentDateTimeUtc()); + void stopTracking(TrackingStopReason reason, time_t current_utc = time(nullptr)); void updateData(); void add10Mins(); diff --git a/client/task.cpp b/client/task.cpp index 16660eb..5728501 100644 --- a/client/task.cpp +++ b/client/task.cpp @@ -726,62 +726,72 @@ int TimeLine::month() int result = 0; // Find first day of month - QDate currentMonth = QDate::currentDate(); - currentMonth.setDate(currentMonth.year(), currentMonth.month(), 1); + date this_month = date::today(); + this_month.mDay = 1; // Find position in time record array close to month begin - TimeArray::iterator lowIter = std::lower_bound(mData.begin(), mData.end(), currentMonth, [] (const TimeRecord& lhs, const QDate& rhs) { return lhs.endTime().toLocalTime().date() < rhs; }); + TimeArray::iterator lowIter = std::lower_bound(mData.begin(), mData.end(), this_month, + [] (const TimeRecord& lhs, const date& rhs) + { + return date::fromTimestamp(lhs.endTime(), date::To_LocalTime) < rhs; + }); - for (;lowIter != mData.end(); lowIter++) + while (lowIter != mData.end()) { // See if start of current time period is later than current month - if (lowIter->startTime().toLocalTime().date().month() > currentMonth.month()) + if (date::fromTimestamp(lowIter->startTime(), date::To_LocalTime).mMonth > this_month.mMonth) break; // quit the loop - if (lowIter->endTime().toLocalTime().date().month() >= currentMonth.month()) + if (date::fromTimestamp(lowIter->endTime(), date::To_LocalTime).mMonth >= this_month.mMonth) { - QDateTime monthBegin(currentMonth, QTime(0,0)); - QDateTime monthEnd(QDate(currentMonth.year(), currentMonth.month(), currentMonth.daysInMonth()), QTime(23, 59, 59)); + // GMT time! + time_t month_begin = this_month.toTimestamp(); + time_t month_end = month_begin + date::daysInMonth(this_month.mYear, this_month.mMonth) * 86400 - 1; - int secondsTo = monthBegin.secsTo(lowIter->startTime().toLocalTime()); + int64_t secondsTo = lowIter->startTime() - month_begin; if (secondsTo > 0) - monthBegin = lowIter->startTime(); + month_begin = lowIter->startTime(); - int secondsFrom = monthEnd.secsTo(lowIter->endTime().toLocalTime()); + int64_t secondsFrom = lowIter->endTime() - month_end; if (secondsFrom < 0) - monthEnd = lowIter->endTime().toLocalTime(); + month_end = lowIter->endTime(); - int secondsSpent = monthBegin.secsTo(monthEnd); + int64_t secondsSpent = month_end - month_begin; result += secondsSpent; } + + lowIter++; } return result; } -int TimeLine::getSum(const QDate& start, const QDate& finish) +int TimeLine::getSum(const date& start, const date& finish) { int result = 0; - TimeArray::iterator lowest = std::lower_bound(mData.begin(), mData.end(), start, [] (const TimeRecord& tr, const QDate& d) { return tr.endTime().toLocalTime().date() < d;}); - //TimeArray::iterator higher = std::upper_bound(mData.begin(), mData.end(), finish, [] (const QDate& d, const TimeRecord& tr) { return tr.startTime().toLocalTime().date() < d;}); + TimeArray::iterator lowest = std::lower_bound(mData.begin(), mData.end(), start, + [] (const TimeRecord& tr, const date& d) + { + return date::fromTimestamp(tr.endTime(), date::To_LocalTime) < d; + }); for (;lowest != mData.end(); lowest++) { TimeRecord& tr = *lowest; - if (tr.startTime().toLocalTime().date() > finish) + if (date::fromTimestamp(tr.startTime(), date::To_LocalTime) > finish) break; - QDateTime dayBegin(start, QTime(0, 0, 0)); - QDateTime dayEnd(finish, QTime(23, 59, 59)); + time_t day_begin = start.toTimestamp(); + time_t day_end = finish.toTimestamp() + 86400 - 1; - if (tr.startTime().toLocalTime().secsTo(dayBegin) < 0) - dayBegin = tr.startTime().toLocalTime(); // Time record begin is later than begin of the interval + if (day_begin - tr.startTime() < 0) + day_begin = tr.startTime(); // Time record begin is later than begin of the interval - if (tr.endTime().toLocalTime().secsTo(dayEnd) > 0) - dayEnd = tr.endTime().toLocalTime(); + if (day_end - tr.endTime() > 0) + day_end = tr.endTime(); - result += dayBegin.secsTo(dayEnd); + result += day_end - day_begin; } return result; } @@ -793,8 +803,9 @@ bool TimeLine::duplicateDetected() const void TimeLine::putDebugRecord() { - QDateTime current = QDateTime::currentDateTimeUtc(); - QDateTime end = current.addSecs(600); + time_t current = time(nullptr); + time_t end = current + 600; + TimeRecord* r = makeNewRecord(current, end); r->save(); } diff --git a/client/task.h b/client/task.h index 01ea9d3..c8956ed 100644 --- a/client/task.h +++ b/client/task.h @@ -11,6 +11,7 @@ #include #include #include "SQLiteCpp/Database.h" +#include "helper.h" typedef int64_t Id; @@ -70,6 +71,7 @@ typedef std::map > DaysMap; typedef std::map > MonthesMap; typedef std::map > YearsMap; + class TimeLine { public: @@ -110,7 +112,7 @@ public: int month(); // Returns number of seconds spent in interval - int getSum(const QDate& start, const QDate& finish); + int getSum(const helper::date& start, const helper::date& finish); // Checks if there duplicate & overllaping time intervals bool duplicateDetected() const; diff --git a/client/timeintervaldlg.cpp b/client/timeintervaldlg.cpp index 7b1d916..7c01341 100644 --- a/client/timeintervaldlg.cpp +++ b/client/timeintervaldlg.cpp @@ -47,7 +47,7 @@ QDateTime TimeIntervalDlg::finishDate() void TimeIntervalDlg::accept() { // Insert interval - mModel->insertInterval(TimeRecord(startDate().toUTC(), finishDate().toUTC(), mTimeline->taskId())); + mModel->insertInterval(TimeRecord(startDate().toUTC().toTime_t(), finishDate().toUTC().toTime_t(), mTimeline->taskId())); emit accepted(); close(); } @@ -68,7 +68,7 @@ void TimeIntervalDlg::closeEvent(QCloseEvent *event) bool TimeIntervalDlg::validate() { assert(mTimeline); - return !mTimeline->hasIntersection(TimeRecord(startDate().toUTC(), finishDate().toUTC(), mTimeline->taskId())); + return !mTimeline->hasIntersection(TimeRecord(startDate().toUTC().toTime_t(), finishDate().toUTC().toTime_t(), mTimeline->taskId())); } void TimeIntervalDlg::dataChanged(const QDateTime& changed) diff --git a/client/timereportwizard.cpp b/client/timereportwizard.cpp index e5772e1..385064f 100644 --- a/client/timereportwizard.cpp +++ b/client/timereportwizard.cpp @@ -5,6 +5,8 @@ #include "helper.h" #include "settings.h" +using namespace helper; + TaskTreePage::TaskTreePage(QWidget *parent) :QWizardPage(parent), mTaskView(nullptr), mTaskModel(nullptr) { @@ -120,7 +122,9 @@ void ReportViewPage::generateReport() t->loadContent(); } - int seconds = t->timeline()->getSum(startDate, finishDate); + date start_date(startDate.year(), startDate.month(), startDate.day()); + date finish_date(finishDate.year(), finishDate.month(), finishDate.day()); + int seconds = t->timeline()->getSum(start_date, finish_date); t->setReportedTime(seconds); t->setChildrenReportedTime(0); if (wasLoaded) @@ -140,14 +144,14 @@ void ReportViewPage::generateReport() { int individualTime = t->getReportedTime(); bool showSeconds = mSettings.data()[KEY_SHOW_SECONDS].toBool(); - QString l1 = helper::chrono::secondsToDisplay(individualTime, showSeconds); + QString l1 = QString::fromStdString(chrono::secondsToDisplay(individualTime, showSeconds)); report += t->path() + " : " + l1; //if (mSettings.data()[KEY_CUMULATIVE_REPORT].toBool()) { int childrenTime = t->getChildrenReportedTime(); if (childrenTime) { - QString l2 = helper::chrono::secondsToDisplay(individualTime + childrenTime, showSeconds); + QString l2 = QString::fromStdString(chrono::secondsToDisplay(individualTime + childrenTime, showSeconds)); report += ". Including subtasks time: " + l2; } } diff --git a/client/timetreemodel.cpp b/client/timetreemodel.cpp index 9c0e7bc..cc2377b 100644 --- a/client/timetreemodel.cpp +++ b/client/timetreemodel.cpp @@ -1,8 +1,11 @@ #include "timetreemodel.h" #include "helper.h" + #include #include +using namespace helper; + #ifdef USE_SIMPLE_TIMETREE TimeTreeModel::TimeTreeModel(PTimeLine timeline) @@ -138,7 +141,7 @@ QModelIndex TimeTreeModel::index(int row, int column, const QModelIndex &parent) switch (l) { case Level_Year: - mTimeLine->getYears(components); + components = mTimeLine->getYears(); iter = components.begin(); std::advance(iter, row); id = PackDate(Level_Year, *iter, 1, 1, 0); @@ -146,7 +149,7 @@ QModelIndex TimeTreeModel::index(int row, int column, const QModelIndex &parent) case Level_Month: // Find monthes set - mTimeLine->getMonthes(year, components); + components = mTimeLine->getMonthes(year); iter = components.begin(); std::advance(iter, row); month = *iter; @@ -157,7 +160,7 @@ QModelIndex TimeTreeModel::index(int row, int column, const QModelIndex &parent) case Level_Day: // Get set of available days - mTimeLine->getDays(year, month, components); + components = mTimeLine->getDays(year, month); // Find day corresponding by requested row iter = components.begin(); @@ -198,19 +201,19 @@ QModelIndex TimeTreeModel::parent(const QModelIndex &child) const return QModelIndex(); case Level_Month: - mTimeLine->getYears(components); + components = mTimeLine->getYears(); iter = components.find(year); row = std::distance(components.begin(), iter); return createIndex(row, 0, PackDate(Level_Year, year, 1, 1, 0)); case Level_Day: - mTimeLine->getMonthes(year, components); + components = mTimeLine->getMonthes(year); iter = components.find(month); row = std::distance(components.begin(), iter); return createIndex(row, 0, PackDate(Level_Month, year, month, 1, 0)); case Level_Time: - mTimeLine->getDays(year, month, components); + components = mTimeLine->getDays(year, month); iter = components.find(day); row = std::distance(components.begin(), iter); return createIndex(row, 0, PackDate(Level_Day, year, month, day, 0)); @@ -238,13 +241,13 @@ int TimeTreeModel::rowCount(const QModelIndex &parent) const { case Level_Month: // Find how much monthes are in that year related records - mTimeLine->getMonthes(year, rows); + rows = mTimeLine->getMonthes(year); result = rows.size(); break; case Level_Day: // Find how much days are in that year&month related records - mTimeLine->getDays(year, month, rows); + rows = mTimeLine->getDays(year, month); result = rows.size(); break; @@ -254,7 +257,7 @@ int TimeTreeModel::rowCount(const QModelIndex &parent) const break; case Level_Year: - mTimeLine->getYears(rows); + rows = mTimeLine->getYears(); result = rows.size(); break; @@ -305,7 +308,9 @@ QVariant TimeTreeModel::data(const QModelIndex &index, int role) const tr = intervals[index.row()]; // Intervals are in local time already - return QString("%1 - %2").arg(helper::chronotr.startTime().time().toString(mTimeFormat), tr.endTime().time().toString(mTimeFormat)); + // ToDo: they are in GMT! + return QString("%1 - %2").arg(QString::fromStdString(chrono::secondsToDisplay(tr.startTime(), false)), + QString::fromStdString(chrono::secondsToDisplay(tr.endTime(), false))); default: return QVariant(); @@ -479,7 +484,7 @@ QModelIndex TimeTreeModel::dayToIndex(const QDate& date) { std::set components; std::set::iterator iter; - mTimeLine->getYears(components); + components = mTimeLine->getYears(); iter = components.find(date.year()); if (iter == components.end()) @@ -487,14 +492,14 @@ QModelIndex TimeTreeModel::dayToIndex(const QDate& date) int yearRow = std::distance(components.begin(), iter); QModelIndex yearIndex = this->createIndex(yearRow, 0, PackDate(Level_Year, date.year(), 1, 1, 0)); - mTimeLine->getMonthes(date.year(), components); + components = mTimeLine->getMonthes(date.year()); iter = components.find(date.month()); if (iter == components.end()) return QModelIndex(); int monthRow = std::distance(components.begin(), iter); QModelIndex monthIndex = this->createIndex(monthRow, 0, PackDate(Level_Month, date.year(), date.month(), 1, 0)); - mTimeLine->getDays(date.year(), date.month(), components); + components = mTimeLine->getDays(date.year(), date.month()); iter = components.find(date.day()); if (iter == components.end()) return QModelIndex();