- refactoring started
This commit is contained in:
parent
e346222c6e
commit
f8d51cf95f
@ -24,7 +24,10 @@ char* __strlcat_chk (char* dest, const char* src, int len, int destcapacity)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
void ThemeHelper::applyCurrentTheme(Settings& settings)
|
|
||||||
|
using namespace helper;
|
||||||
|
|
||||||
|
void theme::applyCurrent(Settings& settings)
|
||||||
{
|
{
|
||||||
// Dark theme
|
// Dark theme
|
||||||
if (settings.data()[KEY_DARK_THEME].toBool())
|
if (settings.data()[KEY_DARK_THEME].toBool())
|
||||||
@ -42,18 +45,36 @@ void ThemeHelper::applyCurrentTheme(Settings& settings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString TimeHelper::secondsToDisplay(int seconds, bool showSeconds)
|
std::string chrono::secondsToDisplay(int seconds, bool showSeconds)
|
||||||
{
|
{
|
||||||
int hours = seconds / 3600;
|
int hours = seconds / 3600;
|
||||||
int minutes = (seconds % 3600) / 60;
|
int minutes = (seconds % 3600) / 60;
|
||||||
int secs = seconds % 60;
|
int secs = seconds % 60;
|
||||||
|
char r[32];
|
||||||
if (showSeconds)
|
if (showSeconds)
|
||||||
return QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'));
|
sprintf(r, "%2d:%2d:%2d", hours, minutes, secs);
|
||||||
else
|
else
|
||||||
return QString("%1:%2").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0'));
|
sprintf(r, "%2d:%2d", hours, minutes);
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathHelper::pathToSettings()
|
std::string chrono::timeToStr(time_t timestamp)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
strftime(buf, sizeof buf, "%FT%TZ", gmtime(×tamp));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t chrono::strToTime(const std::string& s)
|
||||||
|
{
|
||||||
|
struct tm t;
|
||||||
|
memset(&t, 0, sizeof t);
|
||||||
|
strptime(s.c_str(), "%FT%TZ", &t);
|
||||||
|
return timegm(&t);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString path::pathToSettings()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
@ -64,7 +85,7 @@ QString PathHelper::pathToSettings()
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathHelper::pathToDatabase()
|
QString path::pathToDatabase()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
@ -75,7 +96,7 @@ QString PathHelper::pathToDatabase()
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathHelper::pathToDesktop()
|
QString path::pathToDesktop()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
QString folder = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
@ -85,7 +106,7 @@ QString PathHelper::pathToDesktop()
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathHelper::pathToDatabaseTemplate()
|
QString path::pathToDatabaseTemplate()
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WIN
|
#ifdef TARGET_WIN
|
||||||
return QCoreApplication::applicationDirPath() + "/" + DATABASENAME;
|
return QCoreApplication::applicationDirPath() + "/" + DATABASENAME;
|
||||||
@ -96,7 +117,7 @@ QString PathHelper::pathToDatabaseTemplate()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathHelper::pathToLog()
|
QString path::pathToLog()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
@ -106,7 +127,7 @@ QString PathHelper::pathToLog()
|
|||||||
return folder + "/" + LOGNAME;
|
return folder + "/" + LOGNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ActivityTrackerHelper::ensureSmartTrackingIsPossible()
|
bool activityTracker::ensureSmartTrackingIsPossible()
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
HIDActivityTracker tracker;
|
HIDActivityTracker tracker;
|
||||||
|
|||||||
@ -5,46 +5,59 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
class ThemeHelper
|
namespace helper
|
||||||
{
|
{
|
||||||
public:
|
class theme
|
||||||
static void applyCurrentTheme(Settings& settings);
|
{
|
||||||
};
|
public:
|
||||||
|
static void applyCurrent(Settings& settings);
|
||||||
|
};
|
||||||
|
|
||||||
class TimeHelper
|
struct date
|
||||||
{
|
{
|
||||||
public:
|
int mYear = -1, mMonth = -1, mDay = -1;
|
||||||
static QString secondsToDisplay(int seconds, bool showSeconds);
|
|
||||||
};
|
time_t toTimestamp();
|
||||||
|
static date fromTimestamp();
|
||||||
|
};
|
||||||
|
|
||||||
|
class chrono
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string secondsToDisplay(int seconds, bool showSeconds);
|
||||||
|
static std::string timeToStr(time_t timestamp);
|
||||||
|
static time_t strToTime(const std::string& s);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class PathHelper
|
class path
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static QString pathToDatabase();
|
static QString pathToDatabase();
|
||||||
static QString pathToDesktop();
|
static QString pathToDesktop();
|
||||||
static QString pathToSettings();
|
static QString pathToSettings();
|
||||||
static QString pathToDatabaseTemplate();
|
static QString pathToDatabaseTemplate();
|
||||||
static QString pathToLog();
|
static QString pathToLog();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActivityTrackerHelper
|
class activityTracker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool ensureSmartTrackingIsPossible();
|
static bool ensureSmartTrackingIsPossible();
|
||||||
};
|
};
|
||||||
|
|
||||||
class EscapeKeyEventFilter: public QObject
|
class EscapeKeyEventFilter: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EscapeKeyEventFilter(QObject* parent = 0);
|
explicit EscapeKeyEventFilter(QObject* parent = 0);
|
||||||
bool eventFilter(QObject *obj, QEvent * event);
|
bool eventFilter(QObject *obj, QEvent * event);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void escapePressed(QObject* obj);
|
void escapePressed(QObject* obj);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -74,7 +74,7 @@ MainWindow::~MainWindow()
|
|||||||
void MainWindow::attachDatabase()
|
void MainWindow::attachDatabase()
|
||||||
{
|
{
|
||||||
// Open database
|
// Open database
|
||||||
QString path = PathHelper::pathToDatabase();
|
QString path = helper::path::pathToDatabase();
|
||||||
if (mSettings->data()[KEY_DB_FILENAME_SPECIFIED].toBool())
|
if (mSettings->data()[KEY_DB_FILENAME_SPECIFIED].toBool())
|
||||||
path = mSettings->data()[KEY_DB_FILENAME].toString();
|
path = mSettings->data()[KEY_DB_FILENAME].toString();
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ enum class DbProperty
|
|||||||
#define CURRENT_DBVERSION "0"
|
#define CURRENT_DBVERSION "0"
|
||||||
|
|
||||||
// Function to make encryption. Input is raw content blob, output is blob with IV, original length and encrypted data.
|
// Function to make encryption. Input is raw content blob, output is blob with IV, original length and encrypted data.
|
||||||
static void EncryptBlob(const QByteArray& input, QByteArray& output)
|
/*static void EncryptBlob(const QByteArray& input, QByteArray& output)
|
||||||
{
|
{
|
||||||
TwofishCipher cipher;
|
TwofishCipher cipher;
|
||||||
|
|
||||||
@ -39,9 +39,9 @@ static void EncryptBlob(const QByteArray& input, QByteArray& output)
|
|||||||
|
|
||||||
// Encrypt
|
// Encrypt
|
||||||
cipher.encrypt(input, 0, output, iv.length() + 4);
|
cipher.encrypt(input, 0, output, iv.length() + 4);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static void DecryptBlob(const QByteArray& input, QByteArray& output)
|
/*static void DecryptBlob(const QByteArray& input, QByteArray& output)
|
||||||
{
|
{
|
||||||
TwofishCipher cipher;
|
TwofishCipher cipher;
|
||||||
assert(input.length() >= cipher.blocksize() + 4);
|
assert(input.length() >= cipher.blocksize() + 4);
|
||||||
@ -64,7 +64,7 @@ static void DecryptBlob(const QByteArray& input, QByteArray& output)
|
|||||||
|
|
||||||
// Truncate to original size
|
// Truncate to original size
|
||||||
output.truncate(ntohl(lengthNbo));
|
output.truncate(ntohl(lengthNbo));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
Storage::Storage()
|
Storage::Storage()
|
||||||
@ -297,7 +297,7 @@ bool Storage::encryptTask(PTask task)
|
|||||||
|
|
||||||
bool Storage::encryptTaskContent(PTask task)
|
bool Storage::encryptTaskContent(PTask task)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::encryptTaskAttachment(PAttachment attachment)
|
bool Storage::encryptTaskAttachment(PAttachment attachment)
|
||||||
|
|||||||
125
client/task.cpp
125
client/task.cpp
@ -1,8 +1,14 @@
|
|||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(TARGET_OSX) || defined(TARGET_LINUX)
|
||||||
|
# include <uuid/uuid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// -------- WorldId ------
|
// -------- WorldId ------
|
||||||
WorldId::WorldId()
|
WorldId::WorldId()
|
||||||
{
|
{
|
||||||
@ -13,7 +19,7 @@ WorldId::WorldId(const WorldId& src)
|
|||||||
mId = src.mId;
|
mId = src.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldId::WorldId(const QString &s)
|
WorldId::WorldId(const std::string &s)
|
||||||
:mId(s)
|
:mId(s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -30,23 +36,33 @@ WorldId& WorldId::operator = (const WorldId& src)
|
|||||||
|
|
||||||
bool WorldId::operator == (const WorldId& src)
|
bool WorldId::operator == (const WorldId& src)
|
||||||
{
|
{
|
||||||
return mId.isNull() ? false : (mId == src.mId);
|
return mId == src.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldId::operator < (const WorldId& src)
|
bool WorldId::operator < (const WorldId& src)
|
||||||
{
|
{
|
||||||
return mId.isNull() ? true : (mId < src.mId);
|
return mId < src.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WorldId::asString() const
|
std::string WorldId::asString() const
|
||||||
{
|
{
|
||||||
return mId.isNull() ? QString() : mId.toString();
|
return mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldId WorldId::create()
|
WorldId WorldId::create()
|
||||||
{
|
{
|
||||||
WorldId result;
|
WorldId result;
|
||||||
result.mId = QUuid::createUuid();
|
#if defined(TARGET_OSX) || defined(TARGET_LINUX)
|
||||||
|
uuid_t t;
|
||||||
|
uuid_generate(t);
|
||||||
|
char buffer[128];
|
||||||
|
uuid_unparse(t, buffer);
|
||||||
|
result.mId = buffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TARGET_WIN)
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +71,7 @@ TimeRecord::TimeRecord()
|
|||||||
:mId(0), mTaskId(0), mSaved(false)
|
:mId(0), mTaskId(0), mSaved(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
TimeRecord::TimeRecord(const QDateTime &startTime, const QDateTime &endTime, Id taskId)
|
TimeRecord::TimeRecord(const time_t &startTime, const time_t &endTime, Id taskId)
|
||||||
:mId(0), mTaskId(taskId), mSaved(false), mStartTime(startTime), mEndTime(endTime)
|
:mId(0), mTaskId(taskId), mSaved(false), mStartTime(startTime), mEndTime(endTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -63,29 +79,29 @@ TimeRecord::TimeRecord(const QDateTime &startTime, const QDateTime &endTime, Id
|
|||||||
TimeRecord::~TimeRecord()
|
TimeRecord::~TimeRecord()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
QDateTime TimeRecord::endTime() const
|
time_t TimeRecord::endTime() const
|
||||||
{
|
{
|
||||||
return mEndTime;
|
return mEndTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setEndTime(const QDateTime &endTime)
|
void TimeRecord::setEndTime(const time_t &endTime)
|
||||||
{
|
{
|
||||||
mEndTime = endTime;
|
mEndTime = endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime TimeRecord::startTime() const
|
time_t TimeRecord::startTime() const
|
||||||
{
|
{
|
||||||
return mStartTime;
|
return mStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setStartTime(const QDateTime &startTime)
|
void TimeRecord::setStartTime(const time_t &startTime)
|
||||||
{
|
{
|
||||||
mStartTime = startTime;
|
mStartTime = startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimeRecord::length()
|
int TimeRecord::length()
|
||||||
{
|
{
|
||||||
return mStartTime.secsTo(mEndTime);
|
return (int)(mEndTime - mStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id TimeRecord::id() const
|
Id TimeRecord::id() const
|
||||||
@ -123,8 +139,10 @@ void TimeRecord::save()
|
|||||||
if (!mId)
|
if (!mId)
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "insert into timeline(id, starttime, endtime, taskid, removed) values (NULL, :starttime, :endtime, :taskid, :removed)");
|
SQLite::Statement q(Storage::instance().database(), "insert into timeline(id, starttime, endtime, taskid, removed) values (NULL, :starttime, :endtime, :taskid, :removed)");
|
||||||
q.bind(":starttime", mStartTime.toString(Qt::ISODate).toStdString());
|
|
||||||
q.bind(":endtime", mEndTime.toString(Qt::ISODate).toStdString());
|
|
||||||
|
q.bind(":starttime", TimeHelper::timeToStr(mStartTime));
|
||||||
|
q.bind(":endtime", TimeHelper::timeToStr(mEndTime));
|
||||||
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
||||||
q.bind(":removed", 0);
|
q.bind(":removed", 0);
|
||||||
if (q.exec())
|
if (q.exec())
|
||||||
@ -132,9 +150,10 @@ void TimeRecord::save()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "update timeline set starttime = :starttime, endtime = :endtime, taskid = :taskid, removed = 0 where id = :id");
|
SQLite::Statement q(Storage::instance().database(),
|
||||||
q.bind(":starttime", mStartTime.toString(Qt::ISODate).toStdString());
|
"update timeline set starttime = :starttime, endtime = :endtime, taskid = :taskid, removed = 0 where id = :id");
|
||||||
q.bind(":endtime", mEndTime.toString(Qt::ISODate).toStdString());
|
q.bind(":starttime", TimeHelper::timeToStr(mStartTime));
|
||||||
|
q.bind(":endtime", TimeHelper::timeToStr(mEndTime));
|
||||||
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
q.bind(":id", (sqlite3_int64)mId);
|
||||||
q.exec();
|
q.exec();
|
||||||
@ -159,9 +178,9 @@ TimeLine::~TimeLine()
|
|||||||
int TimeLine::findTotalTime()
|
int TimeLine::findTotalTime()
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for(auto timeIter = mData.begin(); timeIter != mData.end(); timeIter++)
|
for(auto& t: mData.begin())
|
||||||
{
|
{
|
||||||
int delta = timeIter->startTime().secsTo(timeIter->endTime());
|
int delta = t.endTime() - t.startTime();
|
||||||
result += delta + 1;
|
result += delta + 1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -186,7 +205,7 @@ void TimeLine::start()
|
|||||||
mActive = true;
|
mActive = true;
|
||||||
|
|
||||||
// Find current time in UTC format
|
// Find current time in UTC format
|
||||||
QDateTime current = QDateTime::currentDateTimeUtc();
|
time_t current = time(nullptr);
|
||||||
|
|
||||||
// Check if current time point does not belong to any existing time interval
|
// Check if current time point does not belong to any existing time interval
|
||||||
if (hasTimePoint(current))
|
if (hasTimePoint(current))
|
||||||
@ -195,7 +214,7 @@ void TimeLine::start()
|
|||||||
mActiveTimeRecord = makeNewRecord(current, current);
|
mActiveTimeRecord = makeNewRecord(current, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeRecord* TimeLine::makeNewRecord(const QDateTime& beginTime, const QDateTime& endTime)
|
TimeRecord* TimeLine::makeNewRecord(time_t beginTime, time_t endTime)
|
||||||
{
|
{
|
||||||
TimeRecord tr;
|
TimeRecord tr;
|
||||||
tr.setStartTime(beginTime);
|
tr.setStartTime(beginTime);
|
||||||
@ -210,14 +229,17 @@ TimeRecord* TimeLine::makeNewRecord(const QDateTime& beginTime, const QDateTime&
|
|||||||
std::reverse_iterator<TimeArray::iterator> intervalIter = std::find_if(std::reverse_iterator<TimeArray::iterator>(mData.end()),
|
std::reverse_iterator<TimeArray::iterator> intervalIter = std::find_if(std::reverse_iterator<TimeArray::iterator>(mData.end()),
|
||||||
std::reverse_iterator<TimeArray::iterator>(mData.begin()),
|
std::reverse_iterator<TimeArray::iterator>(mData.begin()),
|
||||||
[=] (const TimeRecord& tr)
|
[=] (const TimeRecord& tr)
|
||||||
{return tr.id() == intervalId;});
|
{
|
||||||
|
return tr.id() == intervalId;
|
||||||
|
});
|
||||||
|
|
||||||
if (intervalIter != std::reverse_iterator<TimeArray::iterator>(mData.begin()))
|
if (intervalIter != std::reverse_iterator<TimeArray::iterator>(mData.begin()))
|
||||||
return &(*intervalIter);
|
return &(*intervalIter);
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeRecord* TimeLine::hasTimePoint(const QDateTime& t)
|
TimeRecord* TimeLine::hasTimePoint(time_t t)
|
||||||
{
|
{
|
||||||
if (mData.empty())
|
if (mData.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -225,8 +247,10 @@ TimeRecord* TimeLine::hasTimePoint(const QDateTime& t)
|
|||||||
TimeRecord* tr = nullptr;
|
TimeRecord* tr = nullptr;
|
||||||
TimeArray::iterator result;
|
TimeArray::iterator result;
|
||||||
result = std::upper_bound(mData.begin(), mData.end(), t,
|
result = std::upper_bound(mData.begin(), mData.end(), t,
|
||||||
[](const QDateTime& t2, const TimeRecord& tr)
|
[](time_t t2, const TimeRecord& tr)
|
||||||
{ return tr.startTime() > t2;});
|
{
|
||||||
|
return tr.startTime() > t2;
|
||||||
|
});
|
||||||
|
|
||||||
if (result == mData.end())
|
if (result == mData.end())
|
||||||
tr = &mData.last();
|
tr = &mData.last();
|
||||||
@ -251,7 +275,7 @@ bool TimeLine::hasIntersection(const TimeRecord &interval)
|
|||||||
|
|
||||||
TimeArray::iterator result;
|
TimeArray::iterator result;
|
||||||
result = std::upper_bound(mData.begin(), mData.end(), interval.startTime(),
|
result = std::upper_bound(mData.begin(), mData.end(), interval.startTime(),
|
||||||
[](const QDateTime& t2, const TimeRecord& tr)
|
[](time_t t2, const TimeRecord& tr)
|
||||||
{ return tr.startTime() > t2;});
|
{ return tr.startTime() > t2;});
|
||||||
|
|
||||||
if (result == mData.end())
|
if (result == mData.end())
|
||||||
@ -293,7 +317,7 @@ bool TimeLine::removeInterval(const TimeRecord &interval)
|
|||||||
|
|
||||||
TimeArray::iterator result;
|
TimeArray::iterator result;
|
||||||
result = std::upper_bound(mData.begin(), mData.end(), interval.startTime(),
|
result = std::upper_bound(mData.begin(), mData.end(), interval.startTime(),
|
||||||
[](const QDateTime& t2, const TimeRecord& tr)
|
[](time_t t2, const TimeRecord& tr)
|
||||||
{ return tr.startTime() > t2;});
|
{ return tr.startTime() > t2;});
|
||||||
|
|
||||||
if (result == mData.end())
|
if (result == mData.end())
|
||||||
@ -333,7 +357,7 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
// Find interval that startTime() time is greater than interval.endTime()
|
// Find interval that startTime() time is greater than interval.endTime()
|
||||||
TimeArray::iterator iter;
|
TimeArray::iterator iter;
|
||||||
iter = std::upper_bound(mData.begin(), mData.end(), interval.endTime(),
|
iter = std::upper_bound(mData.begin(), mData.end(), interval.endTime(),
|
||||||
[](const QDateTime& t2, const TimeRecord& tr)
|
[](time_t t2, const TimeRecord& tr)
|
||||||
{ return tr.startTime() > t2;});
|
{ return tr.startTime() > t2;});
|
||||||
|
|
||||||
// If all intervals begins later() than requested interval - exit silently
|
// If all intervals begins later() than requested interval - exit silently
|
||||||
@ -354,7 +378,7 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
{
|
{
|
||||||
if (iter->startTime() >= interval.startTime())
|
if (iter->startTime() >= interval.startTime())
|
||||||
{
|
{
|
||||||
iter->setStartTime(iter->endTime().addSecs(1)); // Current interval starts in [interval.startTime(), interval.endTime()], but finishes later
|
iter->setStartTime(iter->endTime() + 1); // Current interval starts in [interval.startTime(), interval.endTime()], but finishes later
|
||||||
iter->save();
|
iter->save();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -363,9 +387,9 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
// So cut interval will split it to 2 new intervals
|
// So cut interval will split it to 2 new intervals
|
||||||
// Also this operation will end loop
|
// Also this operation will end loop
|
||||||
TimeRecord toInsert(*iter); // Backup current interval
|
TimeRecord toInsert(*iter); // Backup current interval
|
||||||
iter->setEndTime(interval.startTime().addSecs(-1));
|
iter->setEndTime(interval.startTime() - 1);
|
||||||
iter->save();
|
iter->save();
|
||||||
toInsert.setStartTime(interval.endTime().addSecs(1));
|
toInsert.setStartTime(interval.endTime() + 1);
|
||||||
mData.insert(++iter, toInsert);
|
mData.insert(++iter, toInsert);
|
||||||
toInsert.save();
|
toInsert.save();
|
||||||
done = true;
|
done = true;
|
||||||
@ -382,7 +406,7 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Current interval starts before cut interval but finishes in cut interval
|
// Current interval starts before cut interval but finishes in cut interval
|
||||||
iter->setEndTime(interval.startTime().addSecs(-1));
|
iter->setEndTime(interval.startTime() - 1);
|
||||||
iter->save();
|
iter->save();
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
@ -396,7 +420,9 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
// Look for exact the same interval as specified one
|
// Look for exact the same interval as specified one
|
||||||
if (!done)
|
if (!done)
|
||||||
{
|
{
|
||||||
iter = std::find_if(mData.begin(), mData.end(), [=] (const TimeRecord& tr) { return tr.id() == interval.id();});
|
iter = std::find_if(mData.begin(), mData.end(),
|
||||||
|
[=] (const TimeRecord& tr)
|
||||||
|
{ return tr.id() == interval.id();});
|
||||||
if (iter != mData.end())
|
if (iter != mData.end())
|
||||||
mData.erase(iter);
|
mData.erase(iter);
|
||||||
}
|
}
|
||||||
@ -405,7 +431,9 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
|
|
||||||
TimeRecord* TimeLine::findIntervalById(Id id)
|
TimeRecord* TimeLine::findIntervalById(Id id)
|
||||||
{
|
{
|
||||||
TimeArray::iterator iter = std::find_if(mData.begin(), mData.end(), [=] (const TimeRecord& tr) { return tr.id() == id;});
|
TimeArray::iterator iter = std::find_if(mData.begin(), mData.end(),
|
||||||
|
[=] (const TimeRecord& tr)
|
||||||
|
{ return tr.id() == id;});
|
||||||
if (iter == mData.end())
|
if (iter == mData.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &(*iter);
|
return &(*iter);
|
||||||
@ -417,20 +445,20 @@ void TimeLine::stop(bool updateTimeline)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (updateTimeline)
|
if (updateTimeline)
|
||||||
flush(true, QDateTime::currentDateTimeUtc());
|
flush(true, time(nullptr));
|
||||||
|
|
||||||
mActive = false;
|
mActive = false;
|
||||||
mActiveTimeRecord = nullptr;
|
mActiveTimeRecord = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeLine::flush(bool saveToDb, const QDateTime& currentUtc)
|
void TimeLine::flush(bool saveToDb, time_t currentUtc)
|
||||||
{
|
{
|
||||||
if (!mActive)
|
if (!mActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mActiveTimeRecord)
|
if (mActiveTimeRecord)
|
||||||
{
|
{
|
||||||
int delta = mActiveTimeRecord->endTime().secsTo(currentUtc);
|
int delta = currentUtc - mActiveTimeRecord->endTime();
|
||||||
mActiveTimeRecord->setEndTime(currentUtc);
|
mActiveTimeRecord->setEndTime(currentUtc);
|
||||||
|
|
||||||
TimeRecord* tr = hasTimePoint(currentUtc);
|
TimeRecord* tr = hasTimePoint(currentUtc);
|
||||||
@ -461,10 +489,8 @@ void TimeLine::load()
|
|||||||
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
||||||
while (q.executeStep())
|
while (q.executeStep())
|
||||||
{
|
{
|
||||||
QDateTime start = QDateTime::fromString(q.getColumn(1).getText(), Qt::ISODate);
|
time_t start = TimeHelper::strToTime(q.getColumn(1).getText());
|
||||||
start.setTimeSpec(Qt::UTC);
|
time_t stop = TimeHelper::strToTime(q.getColumn(2).getText());
|
||||||
QDateTime stop = QDateTime::fromString(q.getColumn(2).getText(), Qt::ISODate);
|
|
||||||
stop.setTimeSpec(Qt::UTC);
|
|
||||||
|
|
||||||
TimeRecord tr;
|
TimeRecord tr;
|
||||||
tr.setId(q.getColumn(0).getInt64());
|
tr.setId(q.getColumn(0).getInt64());
|
||||||
@ -506,13 +532,16 @@ void TimeLine::getYears(std::set<int>& years)
|
|||||||
if (mData.empty())
|
if (mData.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Find lower bound of years - it is first time record
|
struct tm t1, t2;
|
||||||
int year1 = mData.front().startTime().toLocalTime().date().year();
|
localtime(&mData.front().startTime(), &t1);
|
||||||
|
localtime(&mData.back().startTime(), &t2);
|
||||||
|
|
||||||
|
// Find lower bound of years - it is first time record
|
||||||
|
int year1 = t1.tm_year + 1900;
|
||||||
years.insert(year1);
|
years.insert(year1);
|
||||||
|
|
||||||
// Find higher bound of years - it is last time record
|
// Find higher bound of years - it is last time record
|
||||||
int year2 = mData.back().endTime().toLocalTime().date().year();
|
int year2 = t2.tm_year + 1900;
|
||||||
|
|
||||||
if (year1 == year2)
|
if (year1 == year2)
|
||||||
return;
|
return;
|
||||||
@ -521,10 +550,14 @@ void TimeLine::getYears(std::set<int>& years)
|
|||||||
for (int year = year1+1; year <= year2; year++)
|
for (int year = year1+1; year <= year2; year++)
|
||||||
{
|
{
|
||||||
QDate yearStart(year, 1, 1);
|
QDate yearStart(year, 1, 1);
|
||||||
TimeArray::iterator iter = std::lower_bound(mData.begin(), mData.end(), yearStart, [&](const TimeRecord& lhs, const QDate& rhs) { return lhs.endTime().toLocalTime().date() < rhs; });
|
TimeArray::iterator iter = std::lower_bound(mData.begin(), mData.end(), yearStart,
|
||||||
|
[&](const TimeRecord& lhs, time_t rhs)
|
||||||
|
{ return lhs.endTime() < rhs; });
|
||||||
if (iter != mData.end())
|
if (iter != mData.end())
|
||||||
{
|
{
|
||||||
if (iter->startTime().toLocalTime().date().year() <= year)
|
// Get current year
|
||||||
|
struct tm ct; localtime(&iter->startTime(), &ct);
|
||||||
|
if (ct.tm_year + 1900 <= year)
|
||||||
years.insert(year);
|
years.insert(year);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,36 +12,36 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include "SQLiteCpp/Database.h"
|
#include "SQLiteCpp/Database.h"
|
||||||
|
|
||||||
typedef qulonglong Id;
|
typedef uint64_t Id;
|
||||||
|
|
||||||
class WorldId
|
class WorldId
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WorldId();
|
WorldId();
|
||||||
WorldId(const WorldId& src);
|
WorldId(const WorldId& src);
|
||||||
WorldId(const QString& s);
|
WorldId(const std::string& s);
|
||||||
~WorldId();
|
~WorldId();
|
||||||
WorldId& operator = (const WorldId& src);
|
WorldId& operator = (const WorldId& src);
|
||||||
bool operator == (const WorldId& src);
|
bool operator == (const WorldId& src);
|
||||||
bool operator < (const WorldId& src);
|
bool operator < (const WorldId& src);
|
||||||
|
|
||||||
QString asString() const;
|
std::string asString() const;
|
||||||
static WorldId create();
|
static WorldId create();
|
||||||
protected:
|
protected:
|
||||||
QUuid mId;
|
std::string mId;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimeRecord
|
class TimeRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimeRecord();
|
TimeRecord();
|
||||||
TimeRecord(const QDateTime& startTime, const QDateTime& endTime, Id taskId);
|
TimeRecord(const time_t& startTime, const time_t& endTime, Id taskId);
|
||||||
~TimeRecord();
|
~TimeRecord();
|
||||||
|
|
||||||
QDateTime startTime() const;
|
time_t startTime() const;
|
||||||
void setStartTime(const QDateTime& startTime);
|
void setStartTime(const time_t& startTime);
|
||||||
QDateTime endTime() const;
|
time_t endTime() const;
|
||||||
void setEndTime(const QDateTime& endTime);
|
void setEndTime(const time_t& endTime);
|
||||||
int length();
|
int length();
|
||||||
Id id() const;
|
Id id() const;
|
||||||
void setId(Id id);
|
void setId(Id id);
|
||||||
@ -59,7 +59,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
Id mId, mTaskId;
|
Id mId, mTaskId;
|
||||||
WorldId mWorldId;
|
WorldId mWorldId;
|
||||||
QDateTime mStartTime, mEndTime;
|
time_t mStartTime, mEndTime;
|
||||||
bool mSaved;
|
bool mSaved;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public:
|
|||||||
bool active();
|
bool active();
|
||||||
void start();
|
void start();
|
||||||
void stop(bool updateTimeline = true);
|
void stop(bool updateTimeline = true);
|
||||||
void flush(bool saveToDb, const QDateTime& currentUtc);
|
void flush(bool saveToDb, time_t currentUtc);
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void save();
|
void save();
|
||||||
@ -133,10 +133,10 @@ protected:
|
|||||||
int findTotalTime();
|
int findTotalTime();
|
||||||
|
|
||||||
// Builds new time interval record with specified start/finish time
|
// Builds new time interval record with specified start/finish time
|
||||||
TimeRecord* makeNewRecord(const QDateTime& begin, const QDateTime& end);
|
TimeRecord* makeNewRecord(time_t begin, time_t end);
|
||||||
|
|
||||||
// Looks for time record that includes specified time point
|
// Looks for time record that includes specified time point
|
||||||
TimeRecord* hasTimePoint(const QDateTime& t);
|
TimeRecord* hasTimePoint(time_t t);
|
||||||
|
|
||||||
// Sorts records in mData by startTime() value
|
// Sorts records in mData by startTime() value
|
||||||
void sortData();
|
void sortData();
|
||||||
@ -153,8 +153,8 @@ class Task: public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
typedef qulonglong Id;
|
typedef uint64_t Id;
|
||||||
typedef quint32 ModelId;
|
typedef uint32_t ModelId;
|
||||||
enum Flag
|
enum Flag
|
||||||
{
|
{
|
||||||
Flag_NoTimeTracking = 1
|
Flag_NoTimeTracking = 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user