- 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
|
||||
|
||||
#include "settings.h"
|
||||
void ThemeHelper::applyCurrentTheme(Settings& settings)
|
||||
|
||||
using namespace helper;
|
||||
|
||||
void theme::applyCurrent(Settings& settings)
|
||||
{
|
||||
// Dark theme
|
||||
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 minutes = (seconds % 3600) / 60;
|
||||
int secs = seconds % 60;
|
||||
char r[32];
|
||||
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
|
||||
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
|
||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
@ -64,7 +85,7 @@ QString PathHelper::pathToSettings()
|
||||
return path;
|
||||
}
|
||||
|
||||
QString PathHelper::pathToDatabase()
|
||||
QString path::pathToDatabase()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
@ -75,7 +96,7 @@ QString PathHelper::pathToDatabase()
|
||||
return path;
|
||||
}
|
||||
|
||||
QString PathHelper::pathToDesktop()
|
||||
QString path::pathToDesktop()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
@ -85,7 +106,7 @@ QString PathHelper::pathToDesktop()
|
||||
return folder;
|
||||
}
|
||||
|
||||
QString PathHelper::pathToDatabaseTemplate()
|
||||
QString path::pathToDatabaseTemplate()
|
||||
{
|
||||
#ifdef TARGET_WIN
|
||||
return QCoreApplication::applicationDirPath() + "/" + DATABASENAME;
|
||||
@ -96,7 +117,7 @@ QString PathHelper::pathToDatabaseTemplate()
|
||||
#endif
|
||||
}
|
||||
|
||||
QString PathHelper::pathToLog()
|
||||
QString path::pathToLog()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
@ -106,7 +127,7 @@ QString PathHelper::pathToLog()
|
||||
return folder + "/" + LOGNAME;
|
||||
}
|
||||
|
||||
bool ActivityTrackerHelper::ensureSmartTrackingIsPossible()
|
||||
bool activityTracker::ensureSmartTrackingIsPossible()
|
||||
{
|
||||
bool result = false;
|
||||
HIDActivityTracker tracker;
|
||||
|
||||
@ -5,46 +5,59 @@
|
||||
#include <QObject>
|
||||
|
||||
class Settings;
|
||||
class ThemeHelper
|
||||
namespace helper
|
||||
{
|
||||
public:
|
||||
static void applyCurrentTheme(Settings& settings);
|
||||
};
|
||||
class theme
|
||||
{
|
||||
public:
|
||||
static void applyCurrent(Settings& settings);
|
||||
};
|
||||
|
||||
class TimeHelper
|
||||
{
|
||||
public:
|
||||
static QString secondsToDisplay(int seconds, bool showSeconds);
|
||||
};
|
||||
struct date
|
||||
{
|
||||
int mYear = -1, mMonth = -1, mDay = -1;
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
static QString pathToDatabase();
|
||||
static QString pathToDesktop();
|
||||
static QString pathToSettings();
|
||||
static QString pathToDatabaseTemplate();
|
||||
static QString pathToLog();
|
||||
};
|
||||
class path
|
||||
{
|
||||
public:
|
||||
static QString pathToDatabase();
|
||||
static QString pathToDesktop();
|
||||
static QString pathToSettings();
|
||||
static QString pathToDatabaseTemplate();
|
||||
static QString pathToLog();
|
||||
};
|
||||
|
||||
class ActivityTrackerHelper
|
||||
{
|
||||
public:
|
||||
static bool ensureSmartTrackingIsPossible();
|
||||
};
|
||||
class activityTracker
|
||||
{
|
||||
public:
|
||||
static bool ensureSmartTrackingIsPossible();
|
||||
};
|
||||
|
||||
class EscapeKeyEventFilter: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class EscapeKeyEventFilter: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EscapeKeyEventFilter(QObject* parent = 0);
|
||||
bool eventFilter(QObject *obj, QEvent * event);
|
||||
public:
|
||||
explicit EscapeKeyEventFilter(QObject* parent = 0);
|
||||
bool eventFilter(QObject *obj, QEvent * event);
|
||||
|
||||
signals:
|
||||
void escapePressed(QObject* obj);
|
||||
signals:
|
||||
void escapePressed(QObject* obj);
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -74,7 +74,7 @@ MainWindow::~MainWindow()
|
||||
void MainWindow::attachDatabase()
|
||||
{
|
||||
// Open database
|
||||
QString path = PathHelper::pathToDatabase();
|
||||
QString path = helper::path::pathToDatabase();
|
||||
if (mSettings->data()[KEY_DB_FILENAME_SPECIFIED].toBool())
|
||||
path = mSettings->data()[KEY_DB_FILENAME].toString();
|
||||
|
||||
|
||||
@ -8,63 +8,63 @@
|
||||
#endif
|
||||
enum class DbProperty
|
||||
{
|
||||
Version = 1,
|
||||
InternalCipher = 2
|
||||
Version = 1,
|
||||
InternalCipher = 2
|
||||
};
|
||||
|
||||
#define CURRENT_DBVERSION "0"
|
||||
|
||||
// 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;
|
||||
|
||||
// Generate 16 bytes IV
|
||||
QByteArray iv(16, 0);
|
||||
IV::Generate(iv);
|
||||
cipher.setIV(iv);
|
||||
// Generate 16 bytes IV
|
||||
QByteArray iv(16, 0);
|
||||
IV::Generate(iv);
|
||||
cipher.setIV(iv);
|
||||
|
||||
// Make padding
|
||||
int padded = (input.length() % cipher.blocksize()) ? (cipher.blocksize() - input.length() % cipher.blocksize()) : 0;
|
||||
// Make padding
|
||||
int padded = (input.length() % cipher.blocksize()) ? (cipher.blocksize() - input.length() % cipher.blocksize()) : 0;
|
||||
|
||||
// Prepare output buffer
|
||||
output.resize(iv.length() + 4 + input.length() + padded);
|
||||
// Prepare output buffer
|
||||
output.resize(iv.length() + 4 + input.length() + padded);
|
||||
|
||||
// Copy IV
|
||||
memcpy(output.data(), iv.data(), iv.length());
|
||||
// Copy IV
|
||||
memcpy(output.data(), iv.data(), iv.length());
|
||||
|
||||
// Copy original length in network byte order
|
||||
uint32_t lengthNbo = htonl(input.length());
|
||||
memcpy(output.data() + iv.length(), &lengthNbo, 4);
|
||||
// Copy original length in network byte order
|
||||
uint32_t lengthNbo = htonl(input.length());
|
||||
memcpy(output.data() + iv.length(), &lengthNbo, 4);
|
||||
|
||||
// Encrypt
|
||||
cipher.encrypt(input, 0, output, iv.length() + 4);
|
||||
}
|
||||
// Encrypt
|
||||
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;
|
||||
assert(input.length() >= cipher.blocksize() + 4);
|
||||
TwofishCipher cipher;
|
||||
assert(input.length() >= cipher.blocksize() + 4);
|
||||
|
||||
// Read IV
|
||||
QByteArray iv(input.data(), cipher.blocksize());
|
||||
// Read IV
|
||||
QByteArray iv(input.data(), cipher.blocksize());
|
||||
|
||||
// Read original length
|
||||
uint32_t lengthNbo;
|
||||
memcpy(&lengthNbo, input.data() + iv.length(), 4);
|
||||
// Read original length
|
||||
uint32_t lengthNbo;
|
||||
memcpy(&lengthNbo, input.data() + iv.length(), 4);
|
||||
|
||||
// Prepare output buffer
|
||||
output.resize(input.length() - iv.length() - 4);
|
||||
// Prepare output buffer
|
||||
output.resize(input.length() - iv.length() - 4);
|
||||
|
||||
// Set IV
|
||||
cipher.setIV(iv);
|
||||
// Set IV
|
||||
cipher.setIV(iv);
|
||||
|
||||
// Decrypt data
|
||||
cipher.decrypt(input, iv.length() + 4, output, 0);
|
||||
// Decrypt data
|
||||
cipher.decrypt(input, iv.length() + 4, output, 0);
|
||||
|
||||
// Truncate to original size
|
||||
output.truncate(ntohl(lengthNbo));
|
||||
}
|
||||
// Truncate to original size
|
||||
output.truncate(ntohl(lengthNbo));
|
||||
}*/
|
||||
|
||||
|
||||
Storage::Storage()
|
||||
@ -73,186 +73,186 @@ Storage::Storage()
|
||||
|
||||
Storage::~Storage()
|
||||
{
|
||||
close();
|
||||
close();
|
||||
}
|
||||
|
||||
QString Storage::path()
|
||||
{
|
||||
return mPath;
|
||||
return mPath;
|
||||
}
|
||||
|
||||
void Storage::setPath(const QString &path)
|
||||
{
|
||||
mPath = path;
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
QString Storage::key()
|
||||
{
|
||||
return mKey;
|
||||
return mKey;
|
||||
}
|
||||
|
||||
void Storage::setKey(const QString &key)
|
||||
{
|
||||
mKey = key;
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
SQLite::Database& Storage::database()
|
||||
{
|
||||
return *mDatabase;
|
||||
return *mDatabase;
|
||||
}
|
||||
|
||||
bool Storage::create()
|
||||
{
|
||||
assert(!mPath.isEmpty());
|
||||
try
|
||||
{
|
||||
mDatabase = QSharedPointer<SQLite::Database>(new SQLite::Database(mPath.toStdString().c_str(), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE ));
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(!mPath.isEmpty());
|
||||
try
|
||||
{
|
||||
mDatabase = QSharedPointer<SQLite::Database>(new SQLite::Database(mPath.toStdString().c_str(), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE ));
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_ENCRYPTED_DB
|
||||
try
|
||||
{
|
||||
std::string keyQuery = "pragma key='" + mKey.toStdString() + "'";
|
||||
mDatabase->exec(keyQuery.c_str());
|
||||
mDatabase->exec("pragma locking_mode=EXCLUSIVE");
|
||||
mDatabase->exec("pragma journal_mode=MEMORY");
|
||||
mDatabase->exec("pragma temp_store=MEMORY");
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
std::string keyQuery = "pragma key='" + mKey.toStdString() + "'";
|
||||
mDatabase->exec(keyQuery.c_str());
|
||||
mDatabase->exec("pragma locking_mode=EXCLUSIVE");
|
||||
mDatabase->exec("pragma journal_mode=MEMORY");
|
||||
mDatabase->exec("pragma temp_store=MEMORY");
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
// Timeline
|
||||
mDatabase->exec("CREATE TABLE timeline (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, starttime TEXT, endtime TEXT, synctime TEXT)");
|
||||
mDatabase->exec("CREATE INDEX timeline_taskid_index ON timeline(taskid ASC)");
|
||||
try
|
||||
{
|
||||
// Timeline
|
||||
mDatabase->exec("CREATE TABLE timeline (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, starttime TEXT, endtime TEXT, synctime TEXT)");
|
||||
mDatabase->exec("CREATE INDEX timeline_taskid_index ON timeline(taskid ASC)");
|
||||
|
||||
// Tasks tree
|
||||
mDatabase->exec("CREATE TABLE task (type INTEGER, removed INTEGER, modifytime TEXT, id INTEGER PRIMARY KEY, parentid INTEGER, orderid INTEGER, title TEXT, html TEXT, flags INTEGER, synctime1 TEXT, synctime2 TEXT)");
|
||||
mDatabase->exec("CREATE INDEX task_parentid_index ON task(parentid ASC)");
|
||||
// Tasks tree
|
||||
mDatabase->exec("CREATE TABLE task (type INTEGER, removed INTEGER, modifytime TEXT, id INTEGER PRIMARY KEY, parentid INTEGER, orderid INTEGER, title TEXT, html TEXT, flags INTEGER, synctime1 TEXT, synctime2 TEXT)");
|
||||
mDatabase->exec("CREATE INDEX task_parentid_index ON task(parentid ASC)");
|
||||
|
||||
// Attachments
|
||||
mDatabase->exec("CREATE TABLE file (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, filename TEXT, content BLOB, orderid INTEGER, synctime TEXT)");
|
||||
mDatabase->exec("CREATE INDEX file_taskid_index ON file(taskid ASC)");
|
||||
// Attachments
|
||||
mDatabase->exec("CREATE TABLE file (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, filename TEXT, content BLOB, orderid INTEGER, synctime TEXT)");
|
||||
mDatabase->exec("CREATE INDEX file_taskid_index ON file(taskid ASC)");
|
||||
|
||||
// Sync status
|
||||
mDatabase->exec("CREATE TABLE syncs (datetime TEXT, status TEXT)");
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Sync status
|
||||
mDatabase->exec("CREATE TABLE syncs (datetime TEXT, status TEXT)");
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Storage::open()
|
||||
{
|
||||
assert(!mPath.isEmpty());
|
||||
assert(!mPath.isEmpty());
|
||||
|
||||
try
|
||||
{
|
||||
mDatabase = QSharedPointer<SQLite::Database>(new SQLite::Database(mPath.toStdString().c_str(), SQLITE_OPEN_READWRITE));
|
||||
mDatabase->exec("pragma key='" + mKey.toStdString() + "'");
|
||||
SQLite::Statement q(*mDatabase, "select count(*) from sqlite_master");
|
||||
if (!q.executeStep())
|
||||
return false;
|
||||
mDatabase->exec("pragma locking_mode=EXCLUSIVE");
|
||||
mDatabase->exec("pragma journal_mode=MEMORY");
|
||||
mDatabase->exec("pragma temp_store=MEMORY");
|
||||
try
|
||||
{
|
||||
mDatabase = QSharedPointer<SQLite::Database>(new SQLite::Database(mPath.toStdString().c_str(), SQLITE_OPEN_READWRITE));
|
||||
mDatabase->exec("pragma key='" + mKey.toStdString() + "'");
|
||||
SQLite::Statement q(*mDatabase, "select count(*) from sqlite_master");
|
||||
if (!q.executeStep())
|
||||
return false;
|
||||
mDatabase->exec("pragma locking_mode=EXCLUSIVE");
|
||||
mDatabase->exec("pragma journal_mode=MEMORY");
|
||||
mDatabase->exec("pragma temp_store=MEMORY");
|
||||
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
loadTaskTree();
|
||||
return true;
|
||||
loadTaskTree();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Storage::close()
|
||||
{
|
||||
if (mDatabase)
|
||||
{
|
||||
mDatabase.clear();
|
||||
}
|
||||
if (mDatabase)
|
||||
{
|
||||
mDatabase.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool Storage::hasTable(const QString& tablename)
|
||||
{
|
||||
SQLite::Statement tableQuery(*mDatabase, "SELECT name FROM sqlite_master WHERE type='table' AND name=:tablename");
|
||||
tableQuery.bind(":tablename", tablename.toStdString());
|
||||
return tableQuery.executeStep();
|
||||
SQLite::Statement tableQuery(*mDatabase, "SELECT name FROM sqlite_master WHERE type='table' AND name=:tablename");
|
||||
tableQuery.bind(":tablename", tablename.toStdString());
|
||||
return tableQuery.executeStep();
|
||||
}
|
||||
|
||||
bool Storage::upgrade()
|
||||
{
|
||||
int currentVersion = 0;
|
||||
int currentVersion = 0;
|
||||
|
||||
// Check if properties table is here
|
||||
if (!mDatabase)
|
||||
return false;
|
||||
// Check if properties table is here
|
||||
if (!mDatabase)
|
||||
return false;
|
||||
|
||||
if (!hasTable("properties"))
|
||||
{
|
||||
// If not - create it and consider database version 0
|
||||
SQLite::Statement createQuery(*mDatabase, "create table properties(type INTEGER, value TEXT)");
|
||||
if (!createQuery.exec())
|
||||
return false;
|
||||
if (!hasTable("properties"))
|
||||
{
|
||||
// If not - create it and consider database version 0
|
||||
SQLite::Statement createQuery(*mDatabase, "create table properties(type INTEGER, value TEXT)");
|
||||
if (!createQuery.exec())
|
||||
return false;
|
||||
|
||||
// Insert version 0
|
||||
SQLite::Statement insertVersionQuery(*mDatabase, "insert into properties(type, value) values(:proptype, :proptext)");
|
||||
insertVersionQuery.bind(":proptype", (int)DbProperty::Version);
|
||||
insertVersionQuery.bind(":proptext", "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If yes - get database version from 'dbversion' key
|
||||
SQLite::Statement versionQuery(*mDatabase, "select value from properties where type=:proptype");
|
||||
versionQuery.bind(":proptype", (int)DbProperty::Version);
|
||||
if (!versionQuery.executeStep())
|
||||
return false;
|
||||
// Insert version 0
|
||||
SQLite::Statement insertVersionQuery(*mDatabase, "insert into properties(type, value) values(:proptype, :proptext)");
|
||||
insertVersionQuery.bind(":proptype", (int)DbProperty::Version);
|
||||
insertVersionQuery.bind(":proptext", "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If yes - get database version from 'dbversion' key
|
||||
SQLite::Statement versionQuery(*mDatabase, "select value from properties where type=:proptype");
|
||||
versionQuery.bind(":proptype", (int)DbProperty::Version);
|
||||
if (!versionQuery.executeStep())
|
||||
return false;
|
||||
|
||||
QString dbVersionText = versionQuery.getColumn(0).getText("");
|
||||
if (dbVersionText.isEmpty())
|
||||
return false;
|
||||
QString dbVersionText = versionQuery.getColumn(0).getText("");
|
||||
if (dbVersionText.isEmpty())
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
currentVersion = dbVersionText.toInt(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
bool ok = false;
|
||||
currentVersion = dbVersionText.toInt(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Depending on obtained version upgrade database
|
||||
switch (currentVersion)
|
||||
{
|
||||
case 0:
|
||||
if (!upgradeFromVersion0())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
// Depending on obtained version upgrade database
|
||||
switch (currentVersion)
|
||||
{
|
||||
case 0:
|
||||
if (!upgradeFromVersion0())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update version number after upgrade
|
||||
SQLite::Statement updateVersion(*mDatabase, "update table properties set value=:proptext where type=:proptype");
|
||||
updateVersion.bind(":proptext", CURRENT_DBVERSION);
|
||||
updateVersion.bind(":proptype", (int)DbProperty::Version);
|
||||
updateVersion.exec();
|
||||
// Update version number after upgrade
|
||||
SQLite::Statement updateVersion(*mDatabase, "update table properties set value=:proptext where type=:proptype");
|
||||
updateVersion.bind(":proptext", CURRENT_DBVERSION);
|
||||
updateVersion.bind(":proptype", (int)DbProperty::Version);
|
||||
updateVersion.exec();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Storage::upgradeFromVersion0()
|
||||
{
|
||||
/*
|
||||
/*
|
||||
// Upgrade tasks table
|
||||
SQLite::Statement addEncryptedTitle(*mDatabase, "alter table task add column title_encrypted BLOB");
|
||||
if (!addEncryptedTitle.exec())
|
||||
@ -287,94 +287,94 @@ bool Storage::upgradeFromVersion0()
|
||||
std::copy(task->children().begin(), task->children().end(), mTaskToUpgrade.begin() + tl);
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Storage::encryptTask(PTask task)
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::encryptTaskContent(PTask task)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::encryptTaskAttachment(PAttachment attachment)
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PTask Storage::createTask(int index)
|
||||
{
|
||||
if (!mDatabase)
|
||||
return PTask();
|
||||
if (!mDatabase)
|
||||
return PTask();
|
||||
|
||||
SQLite::Statement insertQuery(*mDatabase, "insert into task(id, title, html, parentid, orderid, type, flags) values(NULL, :title, :html, NULL, :orderid, 0, 0)");
|
||||
insertQuery.bind(":title", "");
|
||||
insertQuery.bind(":html", "");
|
||||
insertQuery.bind(":orderid", index);
|
||||
if (insertQuery.exec())
|
||||
{
|
||||
PTask result(new Task());
|
||||
result->setId(database().getLastInsertRowid());
|
||||
result->setIndex(index);
|
||||
mTaskModelIdMap[result->modelId()] = result;
|
||||
mTaskIdMap[result->id()] = result;
|
||||
if (index > mTopTasks.size())
|
||||
mTopTasks.push_back(result);
|
||||
else
|
||||
SQLite::Statement insertQuery(*mDatabase, "insert into task(id, title, html, parentid, orderid, type, flags) values(NULL, :title, :html, NULL, :orderid, 0, 0)");
|
||||
insertQuery.bind(":title", "");
|
||||
insertQuery.bind(":html", "");
|
||||
insertQuery.bind(":orderid", index);
|
||||
if (insertQuery.exec())
|
||||
{
|
||||
mTopTasks.insert(mTopTasks.begin() + index, result);
|
||||
// Assign new indexes for top tasks
|
||||
for (int i=0; i<mTopTasks.size(); i++)
|
||||
{
|
||||
mTopTasks[i]->setIndex(i);
|
||||
mTopTasks[i]->save();
|
||||
}
|
||||
PTask result(new Task());
|
||||
result->setId(database().getLastInsertRowid());
|
||||
result->setIndex(index);
|
||||
mTaskModelIdMap[result->modelId()] = result;
|
||||
mTaskIdMap[result->id()] = result;
|
||||
if (index > mTopTasks.size())
|
||||
mTopTasks.push_back(result);
|
||||
else
|
||||
{
|
||||
mTopTasks.insert(mTopTasks.begin() + index, result);
|
||||
// Assign new indexes for top tasks
|
||||
for (int i=0; i<mTopTasks.size(); i++)
|
||||
{
|
||||
mTopTasks[i]->setIndex(i);
|
||||
mTopTasks[i]->save();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return PTask();
|
||||
else
|
||||
return PTask();
|
||||
}
|
||||
|
||||
PTask Storage::createTask(PTask parent, int index)
|
||||
{
|
||||
if (!parent)
|
||||
return createTask(index);
|
||||
if (!mDatabase)
|
||||
return PTask();
|
||||
if (!parent)
|
||||
return createTask(index);
|
||||
if (!mDatabase)
|
||||
return PTask();
|
||||
|
||||
SQLite::Statement insertQuery(database(), "insert into task(id, title, html, parentid, orderid, type, flags) values(NULL, :title, :html, :parentid, :orderid, 0, 0)");
|
||||
insertQuery.bind(":title", "");
|
||||
insertQuery.bind(":html", "");
|
||||
insertQuery.bind(":parentid", (sqlite3_int64)parent->id());
|
||||
insertQuery.bind(":orderid", index);
|
||||
if (insertQuery.exec())
|
||||
{
|
||||
PTask result(new Task());
|
||||
result->setId(database().getLastInsertRowid());
|
||||
result->setIndex(index);
|
||||
result->setParent(parent);
|
||||
if (index > parent->children().size())
|
||||
parent->children().push_back(result);
|
||||
else
|
||||
SQLite::Statement insertQuery(database(), "insert into task(id, title, html, parentid, orderid, type, flags) values(NULL, :title, :html, :parentid, :orderid, 0, 0)");
|
||||
insertQuery.bind(":title", "");
|
||||
insertQuery.bind(":html", "");
|
||||
insertQuery.bind(":parentid", (sqlite3_int64)parent->id());
|
||||
insertQuery.bind(":orderid", index);
|
||||
if (insertQuery.exec())
|
||||
{
|
||||
parent->children().insert(parent->children().begin() + index, result);
|
||||
for (int i=0; i<parent->children().size(); i++)
|
||||
{
|
||||
parent->children()[i]->setIndex(i);
|
||||
parent->children()[i]->save();
|
||||
}
|
||||
}
|
||||
PTask result(new Task());
|
||||
result->setId(database().getLastInsertRowid());
|
||||
result->setIndex(index);
|
||||
result->setParent(parent);
|
||||
if (index > parent->children().size())
|
||||
parent->children().push_back(result);
|
||||
else
|
||||
{
|
||||
parent->children().insert(parent->children().begin() + index, result);
|
||||
for (int i=0; i<parent->children().size(); i++)
|
||||
{
|
||||
parent->children()[i]->setIndex(i);
|
||||
parent->children()[i]->save();
|
||||
}
|
||||
}
|
||||
|
||||
mTaskModelIdMap[result->modelId()] = result;
|
||||
mTaskIdMap[result->id()] = result;
|
||||
return result;
|
||||
}
|
||||
return PTask();
|
||||
mTaskModelIdMap[result->modelId()] = result;
|
||||
mTaskIdMap[result->id()] = result;
|
||||
return result;
|
||||
}
|
||||
return PTask();
|
||||
}
|
||||
/*
|
||||
PTask Storage::loadTask(Task::Id id, PTask parent)
|
||||
@ -391,264 +391,264 @@ PTask Storage::loadTask(Task::Id id, PTask parent)
|
||||
|
||||
void Storage::saveTask(PTask task, Depth depth)
|
||||
{
|
||||
if (depth == depthSingleTask)
|
||||
saveSingleTask(task);
|
||||
else
|
||||
{
|
||||
saveSingleTask(task);
|
||||
TaskArray& children = task->children();
|
||||
foreach(PTask child, children)
|
||||
saveTask(child, depthRecursive);
|
||||
}
|
||||
if (depth == depthSingleTask)
|
||||
saveSingleTask(task);
|
||||
else
|
||||
{
|
||||
saveSingleTask(task);
|
||||
TaskArray& children = task->children();
|
||||
foreach(PTask child, children)
|
||||
saveTask(child, depthRecursive);
|
||||
}
|
||||
}
|
||||
|
||||
bool Storage::moveTask(PTask task, PTask newParent, int indexToInsert)
|
||||
{
|
||||
bool result = false;
|
||||
task->setParent(newParent);
|
||||
if (newParent)
|
||||
{
|
||||
SQLite::Statement updateParent(database(), "update task set parentid=:parentid where id=:id");
|
||||
updateParent.bind(":parentid", (sqlite3_int64)newParent->id());
|
||||
updateParent.bind(":id", (sqlite3_int64)task->id());
|
||||
result = updateParent.exec();
|
||||
|
||||
// Insert into children list
|
||||
TaskArray& children = newParent->children();
|
||||
if (indexToInsert >= children.size())
|
||||
children.push_back(task);
|
||||
else
|
||||
children.insert(indexToInsert, task);
|
||||
for (int i=0; i<children.size(); i++)
|
||||
bool result = false;
|
||||
task->setParent(newParent);
|
||||
if (newParent)
|
||||
{
|
||||
children[i]->setIndex(i);
|
||||
children[i]->save();
|
||||
SQLite::Statement updateParent(database(), "update task set parentid=:parentid where id=:id");
|
||||
updateParent.bind(":parentid", (sqlite3_int64)newParent->id());
|
||||
updateParent.bind(":id", (sqlite3_int64)task->id());
|
||||
result = updateParent.exec();
|
||||
|
||||
// Insert into children list
|
||||
TaskArray& children = newParent->children();
|
||||
if (indexToInsert >= children.size())
|
||||
children.push_back(task);
|
||||
else
|
||||
children.insert(indexToInsert, task);
|
||||
for (int i=0; i<children.size(); i++)
|
||||
{
|
||||
children[i]->setIndex(i);
|
||||
children[i]->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SQLite::Statement updateToRoot(database(), "update task set parentid = NULL where id=:id");
|
||||
updateToRoot.bind(":id", (sqlite3_int64)task->id());
|
||||
result = updateToRoot.exec();
|
||||
else
|
||||
{
|
||||
SQLite::Statement updateToRoot(database(), "update task set parentid = NULL where id=:id");
|
||||
updateToRoot.bind(":id", (sqlite3_int64)task->id());
|
||||
result = updateToRoot.exec();
|
||||
if (result)
|
||||
task->setParentId(0);
|
||||
|
||||
// Insert into root list
|
||||
if (topOfTaskTree().size() > indexToInsert)
|
||||
topOfTaskTree().insert(indexToInsert, task);
|
||||
else
|
||||
topOfTaskTree().push_back(task);
|
||||
|
||||
for (int i=0; i<topOfTaskTree().size(); i++)
|
||||
{
|
||||
topOfTaskTree()[i]->setIndex(i);
|
||||
topOfTaskTree()[i]->save();
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
task->setParentId(0);
|
||||
|
||||
// Insert into root list
|
||||
if (topOfTaskTree().size() > indexToInsert)
|
||||
topOfTaskTree().insert(indexToInsert, task);
|
||||
else
|
||||
topOfTaskTree().push_back(task);
|
||||
|
||||
for (int i=0; i<topOfTaskTree().size(); i++)
|
||||
{
|
||||
topOfTaskTree()[i]->setIndex(i);
|
||||
topOfTaskTree()[i]->save();
|
||||
task->save();
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
task->save();
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Storage::isOpened()
|
||||
{
|
||||
return mDatabase != nullptr;
|
||||
return mDatabase != nullptr;
|
||||
}
|
||||
|
||||
void Storage::save()
|
||||
{
|
||||
foreach (PTask task, mTopTasks)
|
||||
saveTask(task, depthRecursive);
|
||||
foreach (PTask task, mTopTasks)
|
||||
saveTask(task, depthRecursive);
|
||||
|
||||
database().exec("delete from task where removed = 1");
|
||||
database().exec("delete from timeline where removed = 1");
|
||||
database().exec("delete from file where removed = 1");
|
||||
//database().exec("delete from change where removed = 1");
|
||||
database().exec("delete from task where removed = 1");
|
||||
database().exec("delete from timeline where removed = 1");
|
||||
database().exec("delete from file where removed = 1");
|
||||
//database().exec("delete from change where removed = 1");
|
||||
}
|
||||
|
||||
void Storage::saveSingleTask(PTask task)
|
||||
{
|
||||
task->save();
|
||||
task->save();
|
||||
}
|
||||
|
||||
void Storage::loadTaskTree()
|
||||
{
|
||||
mTopTasks.clear();
|
||||
mTopTasks.clear();
|
||||
|
||||
SQLite::Statement q(database(), "select id, title, orderid, flags, (select count(*) from file where (file.taskid = task.id) and ((file.removed is null) or (file.removed = 0))) from task where (parentid is null) and ((removed != 1) or (removed is null)) order by orderid");
|
||||
int currentIndex = 0;
|
||||
while(q.executeStep())
|
||||
{
|
||||
PTask t(new Task());
|
||||
t->load(q);
|
||||
t->setIndex(currentIndex++);
|
||||
mTaskModelIdMap[t->modelId()] = t;
|
||||
mTaskIdMap[t->id()] = t;
|
||||
mTopTasks.push_back(t);
|
||||
}
|
||||
SQLite::Statement q(database(), "select id, title, orderid, flags, (select count(*) from file where (file.taskid = task.id) and ((file.removed is null) or (file.removed = 0))) from task where (parentid is null) and ((removed != 1) or (removed is null)) order by orderid");
|
||||
int currentIndex = 0;
|
||||
while(q.executeStep())
|
||||
{
|
||||
PTask t(new Task());
|
||||
t->load(q);
|
||||
t->setIndex(currentIndex++);
|
||||
mTaskModelIdMap[t->modelId()] = t;
|
||||
mTaskIdMap[t->id()] = t;
|
||||
mTopTasks.push_back(t);
|
||||
}
|
||||
|
||||
foreach (PTask task, mTopTasks)
|
||||
loadTaskChildren(task);
|
||||
foreach (PTask task, mTopTasks)
|
||||
loadTaskChildren(task);
|
||||
}
|
||||
|
||||
void Storage::loadTaskChildren(PTask task)
|
||||
{
|
||||
SQLite::Statement q(database(), "select id, title, orderid, flags, (select count(*) from file where (file.taskid = task.id) and ((file.removed is null) or (file.removed = 0))) from task where (task.parentid = :parentid) and ((task.removed != 1) or (task.removed is null)) order by task.orderid");
|
||||
q.bind(":parentid", (sqlite3_int64)task->id());
|
||||
int currentIndex = 0;
|
||||
while (q.executeStep())
|
||||
{
|
||||
PTask t(new Task());
|
||||
t->load(q);
|
||||
t->setIndex(currentIndex++);
|
||||
t->setParent(task, false);
|
||||
loadTaskChildren(t);
|
||||
mTaskModelIdMap[t->modelId()] = t;
|
||||
mTaskIdMap[t->id()] = t;
|
||||
task->children().push_back(t);
|
||||
}
|
||||
SQLite::Statement q(database(), "select id, title, orderid, flags, (select count(*) from file where (file.taskid = task.id) and ((file.removed is null) or (file.removed = 0))) from task where (task.parentid = :parentid) and ((task.removed != 1) or (task.removed is null)) order by task.orderid");
|
||||
q.bind(":parentid", (sqlite3_int64)task->id());
|
||||
int currentIndex = 0;
|
||||
while (q.executeStep())
|
||||
{
|
||||
PTask t(new Task());
|
||||
t->load(q);
|
||||
t->setIndex(currentIndex++);
|
||||
t->setParent(task, false);
|
||||
loadTaskChildren(t);
|
||||
mTaskModelIdMap[t->modelId()] = t;
|
||||
mTaskIdMap[t->id()] = t;
|
||||
task->children().push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
PTask Storage::findTaskByModelId(Task::ModelId id)
|
||||
{
|
||||
auto taskIter = mTaskModelIdMap.find(id);
|
||||
if (taskIter != mTaskModelIdMap.end())
|
||||
return *taskIter;
|
||||
else
|
||||
return PTask();
|
||||
auto taskIter = mTaskModelIdMap.find(id);
|
||||
if (taskIter != mTaskModelIdMap.end())
|
||||
return *taskIter;
|
||||
else
|
||||
return PTask();
|
||||
}
|
||||
|
||||
PTask Storage::findTaskById(Task::Id id)
|
||||
{
|
||||
auto taskIter = mTaskIdMap.find(id);
|
||||
if (taskIter != mTaskIdMap.end())
|
||||
return *taskIter;
|
||||
else
|
||||
return PTask();
|
||||
auto taskIter = mTaskIdMap.find(id);
|
||||
if (taskIter != mTaskIdMap.end())
|
||||
return *taskIter;
|
||||
else
|
||||
return PTask();
|
||||
}
|
||||
|
||||
int Storage::findTaskIndexInParent(PTask task)
|
||||
{
|
||||
if (task->parent())
|
||||
return task->parent()->children().indexOf(task);
|
||||
else
|
||||
return topOfTaskTree().indexOf(task);
|
||||
if (task->parent())
|
||||
return task->parent()->children().indexOf(task);
|
||||
else
|
||||
return topOfTaskTree().indexOf(task);
|
||||
}
|
||||
|
||||
TaskArray& Storage::topOfTaskTree()
|
||||
{
|
||||
return mTopTasks;
|
||||
return mTopTasks;
|
||||
}
|
||||
|
||||
void Storage::loadAttachments(PTask task, AttachmentArray& output)
|
||||
{
|
||||
SQLite::Statement q(database(), "select id, filename, orderid from file where (taskid = :taskid) and ((removed != 1) or (removed is null)) order by orderid");
|
||||
q.bind(":taskid", (sqlite3_int64)task->id());
|
||||
while (q.executeStep())
|
||||
{
|
||||
PAttachment att(new Attachment());
|
||||
att->setId(q.getColumn(0).getInt64());
|
||||
att->setFilename(q.getColumn(1).getText());
|
||||
att->setTaskId(task->id());
|
||||
att->setIndex(q.getColumn(2).getInt());
|
||||
output.push_back(att);
|
||||
}
|
||||
SQLite::Statement q(database(), "select id, filename, orderid from file where (taskid = :taskid) and ((removed != 1) or (removed is null)) order by orderid");
|
||||
q.bind(":taskid", (sqlite3_int64)task->id());
|
||||
while (q.executeStep())
|
||||
{
|
||||
PAttachment att(new Attachment());
|
||||
att->setId(q.getColumn(0).getInt64());
|
||||
att->setFilename(q.getColumn(1).getText());
|
||||
att->setTaskId(task->id());
|
||||
att->setIndex(q.getColumn(2).getInt());
|
||||
output.push_back(att);
|
||||
}
|
||||
}
|
||||
|
||||
void Storage::deleteAttachment(PAttachment att)
|
||||
{
|
||||
SQLite::Statement q(database(), "update file set removed=1 where id=:id");
|
||||
q.bind(":id", (sqlite3_int64)att->id());
|
||||
q.exec();
|
||||
SQLite::Statement q(database(), "update file set removed=1 where id=:id");
|
||||
q.bind(":id", (sqlite3_int64)att->id());
|
||||
q.exec();
|
||||
}
|
||||
|
||||
void Storage::undeleteAttachment(PAttachment att)
|
||||
{
|
||||
SQLite::Statement q(database(), "update file set removed=0 where id=:id");
|
||||
q.bind(":id", (sqlite3_int64)att->id());
|
||||
q.exec();
|
||||
SQLite::Statement q(database(), "update file set removed=0 where id=:id");
|
||||
q.bind(":id", (sqlite3_int64)att->id());
|
||||
q.exec();
|
||||
}
|
||||
|
||||
|
||||
Storage& Storage::instance()
|
||||
{
|
||||
static Storage _instance;
|
||||
return _instance;
|
||||
static Storage _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
void Storage::deleteTask(PTask task, DeleteOption option)
|
||||
{
|
||||
if (option != DeleteOption_FromParent)
|
||||
{
|
||||
// Remove from hash
|
||||
removeTask(task);
|
||||
}
|
||||
if (option != DeleteOption_FromParent)
|
||||
{
|
||||
// Remove from hash
|
||||
removeTask(task);
|
||||
}
|
||||
|
||||
TaskArray& siblings = task->parent() ? task->parent()->children() : mTopTasks;
|
||||
siblings.removeOne(task);
|
||||
TaskArray& siblings = task->parent() ? task->parent()->children() : mTopTasks;
|
||||
siblings.removeOne(task);
|
||||
|
||||
// Remove from database
|
||||
if (option == DeleteOption_Total)
|
||||
{
|
||||
SQLite::Statement q(database(), "update task set removed = 1 where id = :id");
|
||||
q.bind(":id", (sqlite3_int64)task->id());
|
||||
q.exec();
|
||||
}
|
||||
// Remove from database
|
||||
if (option == DeleteOption_Total)
|
||||
{
|
||||
SQLite::Statement q(database(), "update task set removed = 1 where id = :id");
|
||||
q.bind(":id", (sqlite3_int64)task->id());
|
||||
q.exec();
|
||||
}
|
||||
|
||||
#if 0
|
||||
int taskIndex = -1;
|
||||
// Update indexes
|
||||
for (int i=0; i<siblings.size(); i++)
|
||||
{
|
||||
if (siblings[i] == task)
|
||||
taskIndex = i;
|
||||
|
||||
Task& t = *siblings[i];
|
||||
if (t.index() > task->index())
|
||||
int taskIndex = -1;
|
||||
// Update indexes
|
||||
for (int i=0; i<siblings.size(); i++)
|
||||
{
|
||||
t.setIndex(t.index() - 1);
|
||||
t.save();
|
||||
}
|
||||
}
|
||||
if (siblings[i] == task)
|
||||
taskIndex = i;
|
||||
|
||||
// Remove from tree
|
||||
if (taskIndex >= 0)
|
||||
siblings.remove(taskIndex);
|
||||
Task& t = *siblings[i];
|
||||
if (t.index() > task->index())
|
||||
{
|
||||
t.setIndex(t.index() - 1);
|
||||
t.save();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from tree
|
||||
if (taskIndex >= 0)
|
||||
siblings.remove(taskIndex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Storage::undeleteTask(PTask task)
|
||||
{
|
||||
SQLite::Statement q(database(), "update task set removed = 0 where id = :id");
|
||||
q.bind(":id", (sqlite3_int64)task->id());
|
||||
q.exec();
|
||||
SQLite::Statement q(database(), "update task set removed = 0 where id = :id");
|
||||
q.bind(":id", (sqlite3_int64)task->id());
|
||||
q.exec();
|
||||
|
||||
// Find place where to insert task
|
||||
TaskArray& siblings = task->parent() ? task->parent()->children() : mTopTasks;
|
||||
// Find place where to insert task
|
||||
TaskArray& siblings = task->parent() ? task->parent()->children() : mTopTasks;
|
||||
|
||||
TaskArray::iterator taskIter = std::lower_bound(siblings.begin(), siblings.end(), task->index(), [] (const PTask& t, int index) { return t->index() < index;});
|
||||
if (taskIter != siblings.end())
|
||||
siblings.insert(taskIter, task);
|
||||
else
|
||||
siblings.append(task);
|
||||
TaskArray::iterator taskIter = std::lower_bound(siblings.begin(), siblings.end(), task->index(), [] (const PTask& t, int index) { return t->index() < index;});
|
||||
if (taskIter != siblings.end())
|
||||
siblings.insert(taskIter, task);
|
||||
else
|
||||
siblings.append(task);
|
||||
|
||||
mTaskModelIdMap[task->modelId()] = task;
|
||||
mTaskIdMap[task->id()] = task;
|
||||
mTaskModelIdMap[task->modelId()] = task;
|
||||
mTaskIdMap[task->id()] = task;
|
||||
}
|
||||
|
||||
void Storage::removeTask(PTask task)
|
||||
{
|
||||
auto taskModelIter = mTaskModelIdMap.find(task->modelId());
|
||||
if (taskModelIter != mTaskModelIdMap.end())
|
||||
mTaskModelIdMap.erase(taskModelIter);
|
||||
auto taskModelIter = mTaskModelIdMap.find(task->modelId());
|
||||
if (taskModelIter != mTaskModelIdMap.end())
|
||||
mTaskModelIdMap.erase(taskModelIter);
|
||||
|
||||
auto taskIter = mTaskIdMap.find(task->id());
|
||||
if (taskIter != mTaskIdMap.end())
|
||||
mTaskIdMap.erase(taskIter);
|
||||
auto taskIter = mTaskIdMap.find(task->id());
|
||||
if (taskIter != mTaskIdMap.end())
|
||||
mTaskIdMap.erase(taskIter);
|
||||
}
|
||||
|
||||
|
||||
1291
client/task.cpp
1291
client/task.cpp
File diff suppressed because it is too large
Load Diff
346
client/task.h
346
client/task.h
@ -12,55 +12,55 @@
|
||||
#include <map>
|
||||
#include "SQLiteCpp/Database.h"
|
||||
|
||||
typedef qulonglong Id;
|
||||
typedef uint64_t Id;
|
||||
|
||||
class WorldId
|
||||
{
|
||||
public:
|
||||
WorldId();
|
||||
WorldId(const WorldId& src);
|
||||
WorldId(const QString& s);
|
||||
~WorldId();
|
||||
WorldId& operator = (const WorldId& src);
|
||||
bool operator == (const WorldId& src);
|
||||
bool operator < (const WorldId& src);
|
||||
WorldId();
|
||||
WorldId(const WorldId& src);
|
||||
WorldId(const std::string& s);
|
||||
~WorldId();
|
||||
WorldId& operator = (const WorldId& src);
|
||||
bool operator == (const WorldId& src);
|
||||
bool operator < (const WorldId& src);
|
||||
|
||||
QString asString() const;
|
||||
static WorldId create();
|
||||
std::string asString() const;
|
||||
static WorldId create();
|
||||
protected:
|
||||
QUuid mId;
|
||||
std::string mId;
|
||||
};
|
||||
|
||||
class TimeRecord
|
||||
{
|
||||
public:
|
||||
TimeRecord();
|
||||
TimeRecord(const QDateTime& startTime, const QDateTime& endTime, Id taskId);
|
||||
~TimeRecord();
|
||||
TimeRecord();
|
||||
TimeRecord(const time_t& startTime, const time_t& endTime, Id taskId);
|
||||
~TimeRecord();
|
||||
|
||||
QDateTime startTime() const;
|
||||
void setStartTime(const QDateTime& startTime);
|
||||
QDateTime endTime() const;
|
||||
void setEndTime(const QDateTime& endTime);
|
||||
int length();
|
||||
Id id() const;
|
||||
void setId(Id id);
|
||||
Id taskId() const;
|
||||
void setTaskId(Id id);
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
time_t startTime() const;
|
||||
void setStartTime(const time_t& startTime);
|
||||
time_t endTime() const;
|
||||
void setEndTime(const time_t& endTime);
|
||||
int length();
|
||||
Id id() const;
|
||||
void setId(Id id);
|
||||
Id taskId() const;
|
||||
void setTaskId(Id id);
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
|
||||
// Save record to DB. If record is new - id() property will be set after this call.
|
||||
void save();
|
||||
// Save record to DB. If record is new - id() property will be set after this call.
|
||||
void save();
|
||||
|
||||
// Remove record from DB.
|
||||
void deleteRecord();
|
||||
// Remove record from DB.
|
||||
void deleteRecord();
|
||||
|
||||
protected:
|
||||
Id mId, mTaskId;
|
||||
WorldId mWorldId;
|
||||
QDateTime mStartTime, mEndTime;
|
||||
bool mSaved;
|
||||
Id mId, mTaskId;
|
||||
WorldId mWorldId;
|
||||
time_t mStartTime, mEndTime;
|
||||
bool mSaved;
|
||||
};
|
||||
|
||||
typedef QVector<TimeRecord> TimeArray;
|
||||
@ -73,73 +73,73 @@ typedef std::map<int, QSharedPointer<MonthesMap> > YearsMap;
|
||||
class TimeLine
|
||||
{
|
||||
public:
|
||||
TimeLine();
|
||||
~TimeLine();
|
||||
TimeLine();
|
||||
~TimeLine();
|
||||
|
||||
TimeArray& data();
|
||||
TimeArray& data();
|
||||
|
||||
// Returns total time in seconds
|
||||
int totalTime();
|
||||
bool active();
|
||||
void start();
|
||||
void stop(bool updateTimeline = true);
|
||||
void flush(bool saveToDb, const QDateTime& currentUtc);
|
||||
// Returns total time in seconds
|
||||
int totalTime();
|
||||
bool active();
|
||||
void start();
|
||||
void stop(bool updateTimeline = true);
|
||||
void flush(bool saveToDb, time_t currentUtc);
|
||||
|
||||
void load();
|
||||
void save();
|
||||
void load();
|
||||
void save();
|
||||
|
||||
Id taskId();
|
||||
void setTaskId(Id id);
|
||||
Id taskId();
|
||||
void setTaskId(Id id);
|
||||
|
||||
// These methods work with local time
|
||||
void getYears(std::set<int>& result);
|
||||
void getMonthes(int year, std::set<int>& result);
|
||||
void getDays(int year, int month, std::set<int>& result);
|
||||
int getTime(int year, int month, int day, std::vector<TimeRecord>* intervals);
|
||||
// These methods work with local time
|
||||
void getYears(std::set<int>& result);
|
||||
void getMonthes(int year, std::set<int>& result);
|
||||
void getDays(int year, int month, std::set<int>& result);
|
||||
int getTime(int year, int month, int day, std::vector<TimeRecord>* intervals);
|
||||
|
||||
int today();
|
||||
int month();
|
||||
int getSum(const QDate& start, const QDate& finish);
|
||||
bool duplicateDetected() const;
|
||||
int today();
|
||||
int month();
|
||||
int getSum(const QDate& start, const QDate& finish);
|
||||
bool duplicateDetected() const;
|
||||
|
||||
// Checks if specified interval has intersection
|
||||
bool hasIntersection(const TimeRecord& interval);
|
||||
// Checks if specified interval has intersection
|
||||
bool hasIntersection(const TimeRecord& interval);
|
||||
|
||||
// Inserts new interval to timeline. Saves new interval to DB.
|
||||
void insertInterval(const TimeRecord& interval);
|
||||
// Inserts new interval to timeline. Saves new interval to DB.
|
||||
void insertInterval(const TimeRecord& interval);
|
||||
|
||||
// Attempts to find & remove from timeline specified interval. Returns true if succeeded. Removes interval from DB too.
|
||||
// Search is made using start/finish time interval value - not id() value. Only whole TimeRecord can be deleted.
|
||||
bool removeInterval(const TimeRecord& interval);
|
||||
// Attempts to find & remove from timeline specified interval. Returns true if succeeded. Removes interval from DB too.
|
||||
// Search is made using start/finish time interval value - not id() value. Only whole TimeRecord can be deleted.
|
||||
bool removeInterval(const TimeRecord& interval);
|
||||
|
||||
// Attempts to find & cut interval from timeline.
|
||||
// It does not mean whole TimeRecord will be removed. Depending on interval bounds existing TimeRecord can be removed/modified/add new records even.
|
||||
void cutInterval(const TimeRecord& interval);
|
||||
// Attempts to find & cut interval from timeline.
|
||||
// It does not mean whole TimeRecord will be removed. Depending on interval bounds existing TimeRecord can be removed/modified/add new records even.
|
||||
void cutInterval(const TimeRecord& interval);
|
||||
|
||||
// Searches time interval by its id. Can return NULL if search failed.
|
||||
TimeRecord* findIntervalById(Id id);
|
||||
// Searches time interval by its id. Can return NULL if search failed.
|
||||
TimeRecord* findIntervalById(Id id);
|
||||
|
||||
// Adds 10 minutes interval starting from current time. For debug/test purposes.
|
||||
void putDebugRecord();
|
||||
// Adds 10 minutes interval starting from current time. For debug/test purposes.
|
||||
void putDebugRecord();
|
||||
|
||||
protected:
|
||||
TimeArray mData;
|
||||
Id mTaskId;
|
||||
bool mActive;
|
||||
TimeRecord* mActiveTimeRecord;
|
||||
int mTotalTime;
|
||||
TimeArray mData;
|
||||
Id mTaskId;
|
||||
bool mActive;
|
||||
TimeRecord* mActiveTimeRecord;
|
||||
int mTotalTime;
|
||||
|
||||
// Sums total time in timeline
|
||||
int findTotalTime();
|
||||
// Sums total time in timeline
|
||||
int findTotalTime();
|
||||
|
||||
// Builds new time interval record with specified start/finish time
|
||||
TimeRecord* makeNewRecord(const QDateTime& begin, const QDateTime& end);
|
||||
// Builds new time interval record with specified start/finish time
|
||||
TimeRecord* makeNewRecord(time_t begin, time_t end);
|
||||
|
||||
// Looks for time record that includes specified time point
|
||||
TimeRecord* hasTimePoint(const QDateTime& t);
|
||||
// Looks for time record that includes specified time point
|
||||
TimeRecord* hasTimePoint(time_t t);
|
||||
|
||||
// Sorts records in mData by startTime() value
|
||||
void sortData();
|
||||
// Sorts records in mData by startTime() value
|
||||
void sortData();
|
||||
|
||||
};
|
||||
|
||||
@ -151,139 +151,139 @@ typedef QVector<PTask> TaskArray;
|
||||
|
||||
class Task: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef qulonglong Id;
|
||||
typedef quint32 ModelId;
|
||||
enum Flag
|
||||
{
|
||||
Flag_NoTimeTracking = 1
|
||||
};
|
||||
typedef uint64_t Id;
|
||||
typedef uint32_t ModelId;
|
||||
enum Flag
|
||||
{
|
||||
Flag_NoTimeTracking = 1
|
||||
};
|
||||
|
||||
Task();
|
||||
~Task();
|
||||
Task();
|
||||
~Task();
|
||||
|
||||
void load(SQLite::Statement& q);
|
||||
void load(SQLite::Statement& q);
|
||||
|
||||
Id id() const;
|
||||
void setId(Id id);
|
||||
Id id() const;
|
||||
void setId(Id id);
|
||||
|
||||
Id parentId() const;
|
||||
void setParentId(Id id);
|
||||
Id parentId() const;
|
||||
void setParentId(Id id);
|
||||
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
|
||||
ModelId modelId() const;
|
||||
void setModelId(ModelId id);
|
||||
ModelId modelId() const;
|
||||
void setModelId(ModelId id);
|
||||
|
||||
int index() const;
|
||||
void setIndex(int index, bool modified = true);
|
||||
int index() const;
|
||||
void setIndex(int index, bool modified = true);
|
||||
|
||||
enum SaveOptions
|
||||
{
|
||||
Save_Automatic,
|
||||
Save_Forced
|
||||
};
|
||||
enum SaveOptions
|
||||
{
|
||||
Save_Automatic,
|
||||
Save_Forced
|
||||
};
|
||||
|
||||
void save(SaveOptions options = Save_Automatic);
|
||||
void save(SaveOptions options = Save_Automatic);
|
||||
|
||||
QString html() const;
|
||||
void setHtml(const QString& html);
|
||||
QString title() const;
|
||||
void setTitle(const QString& title, bool modified = true);
|
||||
QString html() const;
|
||||
void setHtml(const QString& html);
|
||||
QString title() const;
|
||||
void setTitle(const QString& title, bool modified = true);
|
||||
|
||||
QString path() const;
|
||||
QString path() const;
|
||||
|
||||
PTask parent() const;
|
||||
void setParent(PTask task, bool modified = true);
|
||||
PTask parent() const;
|
||||
void setParent(PTask task, bool modified = true);
|
||||
|
||||
TaskArray& children();
|
||||
TaskArray& children();
|
||||
|
||||
// Loads html and timeline
|
||||
void loadContent();
|
||||
bool isContentLoaded() const;
|
||||
// Loads html and timeline
|
||||
void loadContent();
|
||||
bool isContentLoaded() const;
|
||||
|
||||
// Unloads html and timeline
|
||||
void unloadContent(bool includeTimeline = true);
|
||||
// Unloads html and timeline
|
||||
void unloadContent(bool includeTimeline = true);
|
||||
|
||||
PTimeLine timeline();
|
||||
PTimeLine timeline();
|
||||
|
||||
// Returns true if task has attachments
|
||||
int getAttachmentCount();
|
||||
void setAttachmentCount(int count);
|
||||
int checkAttachments();
|
||||
// Returns true if task has attachments
|
||||
int getAttachmentCount();
|
||||
void setAttachmentCount(int count);
|
||||
int checkAttachments();
|
||||
|
||||
// Service properties used in time reporting
|
||||
bool isChecked() const;
|
||||
void setChecked(bool checked);
|
||||
// Service properties used in time reporting
|
||||
bool isChecked() const;
|
||||
void setChecked(bool checked);
|
||||
|
||||
int getReportedTime() const;
|
||||
void setReportedTime(int t);
|
||||
int getReportedTime() const;
|
||||
void setReportedTime(int t);
|
||||
|
||||
int getChildrenReportedTime() const;
|
||||
void setChildrenReportedTime(int t);
|
||||
int getChildrenReportedTime() const;
|
||||
void setChildrenReportedTime(int t);
|
||||
|
||||
int flags() const;
|
||||
void setFlags(int value);
|
||||
int flags() const;
|
||||
void setFlags(int value);
|
||||
|
||||
int cursorPosition() const;
|
||||
void setCursorPosition(int position);
|
||||
int cursorPosition() const;
|
||||
void setCursorPosition(int position);
|
||||
|
||||
/*
|
||||
/*
|
||||
QUndoStack* getUndoStack() const;
|
||||
void setUndoStack(QUndoStack* doc);
|
||||
*/
|
||||
|
||||
protected:
|
||||
QString mHtml, mTitle;
|
||||
PTimeLine mTimeLine;
|
||||
Id mId, mParentId;
|
||||
WorldId mWorldId;
|
||||
ModelId mModelId;
|
||||
bool mTitleModified, mHtmlModified, mHtmlLoaded, mIndexModified, mParentModified;
|
||||
PTask mParent;
|
||||
TaskArray mChildren;
|
||||
int mIndex;
|
||||
bool mChecked;
|
||||
int mReportedTime, mChildrenReportedTime;
|
||||
int mAttachmentCount;
|
||||
int mFlags;
|
||||
QTextDocument* mDocument;
|
||||
int mCursorPosition;
|
||||
QString mHtml, mTitle;
|
||||
PTimeLine mTimeLine;
|
||||
Id mId, mParentId;
|
||||
WorldId mWorldId;
|
||||
ModelId mModelId;
|
||||
bool mTitleModified, mHtmlModified, mHtmlLoaded, mIndexModified, mParentModified;
|
||||
PTask mParent;
|
||||
TaskArray mChildren;
|
||||
int mIndex;
|
||||
bool mChecked;
|
||||
int mReportedTime, mChildrenReportedTime;
|
||||
int mAttachmentCount;
|
||||
int mFlags;
|
||||
QTextDocument* mDocument;
|
||||
int mCursorPosition;
|
||||
};
|
||||
|
||||
class Attachment
|
||||
{
|
||||
public:
|
||||
Attachment();
|
||||
~Attachment();
|
||||
Attachment();
|
||||
~Attachment();
|
||||
|
||||
Task::Id id();
|
||||
void setId(Task::Id id);
|
||||
Task::Id id();
|
||||
void setId(Task::Id id);
|
||||
|
||||
Task::Id taskId();
|
||||
void setTaskId(Task::Id id);
|
||||
Task::Id taskId();
|
||||
void setTaskId(Task::Id id);
|
||||
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
WorldId worldId() const;
|
||||
void setWorldId(const WorldId& id);
|
||||
|
||||
int index();
|
||||
void setIndex(int index);
|
||||
int index();
|
||||
void setIndex(int index);
|
||||
|
||||
QByteArray loadContent();
|
||||
void saveContent(const QByteArray& content);
|
||||
QByteArray loadContent();
|
||||
void saveContent(const QByteArray& content);
|
||||
|
||||
void setFilename(const QString& filename);
|
||||
QString filename();
|
||||
void setFilename(const QString& filename);
|
||||
QString filename();
|
||||
|
||||
void save();
|
||||
void load();
|
||||
void save();
|
||||
void load();
|
||||
protected:
|
||||
Id mId, mTaskId;
|
||||
WorldId mWorldId;
|
||||
QString mFilename;
|
||||
int mIndex;
|
||||
Id mId, mTaskId;
|
||||
WorldId mWorldId;
|
||||
QString mFilename;
|
||||
int mIndex;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<Attachment> PAttachment;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user