- all storage related logic moved to Storage class + fix non removed time intervals
This commit is contained in:
parent
45d27bf48d
commit
fc0d501c05
@ -180,23 +180,23 @@ void AttachmentsList::importFile()
|
|||||||
QByteArray compressed = qCompress(content);
|
QByteArray compressed = qCompress(content);
|
||||||
|
|
||||||
// Put it to Attachment instance
|
// Put it to Attachment instance
|
||||||
PAttachment att(new Attachment());
|
|
||||||
att->setTaskId(mTask->id());
|
|
||||||
att->setIndex(mModel->rowCount());
|
|
||||||
QFileInfo fi(filename);
|
QFileInfo fi(filename);
|
||||||
att->setFilename(fi.fileName());
|
PAttachment att(new Attachment());
|
||||||
|
att->setTaskId(mTask->id())
|
||||||
|
.setIndex(mModel->rowCount())
|
||||||
|
.setFilename(fi.fileName());
|
||||||
|
|
||||||
// Save everything
|
// Save everything
|
||||||
att->save();
|
att->saveMetadata()
|
||||||
att->saveContent(compressed);
|
.saveContent(compressed);
|
||||||
|
|
||||||
mModel->addItem(att);
|
mModel->addItem(att);
|
||||||
}
|
}
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh hasAttachments property on owner task
|
// Refresh AttachmentsCount property on owner task
|
||||||
mTask->checkAttachments();
|
mTask->preloadAttachmentCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachmentsList::exportFile()
|
void AttachmentsList::exportFile()
|
||||||
@ -242,13 +242,13 @@ void AttachmentsList::deleteFile()
|
|||||||
for (int row = index.row() + 1; row < mModel->rowCount(); row++)
|
for (int row = index.row() + 1; row < mModel->rowCount(); row++)
|
||||||
{
|
{
|
||||||
Attachment& att = *mModel->itemAt(row);
|
Attachment& att = *mModel->itemAt(row);
|
||||||
att.setIndex(att.index() - 1);
|
att.setIndex(att.index() - 1)
|
||||||
att.save();
|
.saveMetadata();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh hasAttachment property value on task
|
// Refresh hasAttachment property value on task
|
||||||
mTask->checkAttachments();
|
mTask->preloadAttachmentCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachmentsList::renameFile()
|
void AttachmentsList::renameFile()
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
// Auto generated file ! Please do not edit !
|
// Auto generated file ! Please do not edit !
|
||||||
#define APP_BUILD_NUMBER 177
|
#define APP_BUILD_NUMBER 214
|
||||||
@ -310,13 +310,15 @@ bool EscapeKeyEventFilter::eventFilter(QObject *obj, QEvent * event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString password::load()
|
QString password::loadFromKeychain()
|
||||||
{
|
{
|
||||||
QKeychain::ReadPasswordJob job(APPNAME);
|
QKeychain::ReadPasswordJob job(APPNAME);
|
||||||
job.setKey(KEY_PASSWORD);
|
job.setKey(KEY_PASSWORD);
|
||||||
job.setAutoDelete(false);
|
job.setAutoDelete(false);
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
||||||
|
|
||||||
|
// Start job
|
||||||
job.start();
|
job.start();
|
||||||
loop.exec();
|
loop.exec();
|
||||||
if (job.error())
|
if (job.error())
|
||||||
@ -325,12 +327,14 @@ QString password::load()
|
|||||||
return job.textData();
|
return job.textData();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool password::save(const QString& password)
|
bool password::saveToKeychain(const QString &password)
|
||||||
{
|
{
|
||||||
QKeychain::WritePasswordJob job(APPNAME);
|
QKeychain::WritePasswordJob job(APPNAME);
|
||||||
job.setKey(KEY_PASSWORD);
|
job.setKey(KEY_PASSWORD);
|
||||||
job.setAutoDelete(false);
|
job.setAutoDelete(false);
|
||||||
job.setTextData(password);
|
job.setTextData(password);
|
||||||
|
|
||||||
|
// Start job
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
||||||
job.start();
|
job.start();
|
||||||
|
|||||||
@ -94,11 +94,12 @@ namespace helper
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Keychain helper class
|
||||||
class password
|
class password
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static QString load();
|
static QString loadFromKeychain();
|
||||||
static bool save(const QString& password);
|
static bool saveToKeychain(const QString& password);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::string app_version();
|
extern std::string app_version();
|
||||||
|
|||||||
@ -18,37 +18,6 @@ int main(int argc, char *argv[])
|
|||||||
QString folder = QFileInfo(path).absoluteDir().path();
|
QString folder = QFileInfo(path).absoluteDir().path();
|
||||||
Storage::instance().setPath(path);
|
Storage::instance().setPath(path);
|
||||||
|
|
||||||
// Check if file exists at all
|
|
||||||
/*if (!QFile::exists(path))
|
|
||||||
{
|
|
||||||
// Show dialog that requests database path
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if password is available
|
|
||||||
if (Settings::instance().data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
|
||||||
{
|
|
||||||
QString password = helper::password::load();
|
|
||||||
if (password.isEmpty())
|
|
||||||
{
|
|
||||||
// Ask about password
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Storage::instance().setKey(password);
|
|
||||||
if (!Storage::instance().open())
|
|
||||||
{
|
|
||||||
askDbPassword(tr("Invalid password, please try again."));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
QApplication::postEvent(this, new UiInitEvent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
askDbPassword(QString());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.layout()->invalidate();
|
w.layout()->invalidate();
|
||||||
|
|
||||||
|
|||||||
@ -91,19 +91,11 @@ void MainWindow::attachDatabase()
|
|||||||
{
|
{
|
||||||
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
||||||
{
|
{
|
||||||
QString password = helper::password::load();
|
QString password = helper::password::loadFromKeychain();
|
||||||
if (password.isEmpty())
|
if (password.isEmpty())
|
||||||
askDbPassword();
|
askDbPassword();
|
||||||
else
|
else
|
||||||
{
|
onDbPasswordEntered(password);
|
||||||
Storage::instance().setKey(password);
|
|
||||||
if (!Storage::instance().open())
|
|
||||||
{
|
|
||||||
askDbPassword(tr("Invalid password, please try again."));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
QApplication::postEvent(this, new ClientEvent<UiInitId>());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
askDbPassword(QString());
|
askDbPassword(QString());
|
||||||
@ -465,7 +457,7 @@ void MainWindow::preferences()
|
|||||||
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool() == false)
|
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool() == false)
|
||||||
{
|
{
|
||||||
// Reset password in keychain
|
// Reset password in keychain
|
||||||
helper::password::save(QString(""));
|
helper::password::saveToKeychain(QString(""));
|
||||||
|
|
||||||
//mSettings->data()[KEY_PASSWORD] = NOPASSWORDSTRING;
|
//mSettings->data()[KEY_PASSWORD] = NOPASSWORDSTRING;
|
||||||
mSettings->save();
|
mSettings->save();
|
||||||
@ -1672,7 +1664,7 @@ void MainWindow::onDbPasswordEntered(const QString& password)
|
|||||||
{
|
{
|
||||||
// Save password to keychain if needed
|
// Save password to keychain if needed
|
||||||
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
||||||
helper::password::save(password);
|
helper::password::saveToKeychain(password);
|
||||||
|
|
||||||
// Try to open database
|
// Try to open database
|
||||||
Storage::instance().setKey(password);
|
Storage::instance().setKey(password);
|
||||||
@ -1694,7 +1686,7 @@ void MainWindow::onNewDbPasswordEntered(const QString& password)
|
|||||||
{
|
{
|
||||||
// Save password to keychain if needed
|
// Save password to keychain if needed
|
||||||
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
if (mSettings->data()[KEY_AUTOSAVE_PASSWORD].toBool())
|
||||||
helper::password::save(password);
|
helper::password::saveToKeychain(password);
|
||||||
|
|
||||||
// Configure storage
|
// Configure storage
|
||||||
Storage::instance().setKey(password);
|
Storage::instance().setKey(password);
|
||||||
|
|||||||
@ -75,7 +75,7 @@ void PreferencesDlg::accepted()
|
|||||||
{
|
{
|
||||||
bool savePassword = ui->mAutosavePasswordCheckbox->isChecked();
|
bool savePassword = ui->mAutosavePasswordCheckbox->isChecked();
|
||||||
mSettings.data()[KEY_AUTOSAVE_PASSWORD] = savePassword;
|
mSettings.data()[KEY_AUTOSAVE_PASSWORD] = savePassword;
|
||||||
helper::password::save(savePassword ? Storage::instance().key() : QString(""));
|
helper::password::saveToKeychain(savePassword ? Storage::instance().key() : QString(""));
|
||||||
|
|
||||||
mSettings.data()[KEY_SHOW_SECONDS] = ui->mShowSecondsCheckbox->isChecked();
|
mSettings.data()[KEY_SHOW_SECONDS] = ui->mShowSecondsCheckbox->isChecked();
|
||||||
mSettings.data()[KEY_ASK_BEFORE_DELETE] = ui->mAskBeforeDeleteCheckbox->isChecked();
|
mSettings.data()[KEY_ASK_BEFORE_DELETE] = ui->mAskBeforeDeleteCheckbox->isChecked();
|
||||||
|
|||||||
@ -135,36 +135,68 @@ bool Storage::create()
|
|||||||
// Synctime & timestamp are always milliseconds from the start of UNIX epoch.
|
// Synctime & timestamp are always milliseconds from the start of UNIX epoch.
|
||||||
|
|
||||||
// Timeline
|
// Timeline
|
||||||
mDatabase->exec("CREATE TABLE timeline (id INTEGER PRIMARY KEY, removed INTEGER, "
|
mDatabase->exec("CREATE TABLE timeline ("
|
||||||
"taskid INTEGER, starttime TEXT, endtime TEXT, timestamp INTEGER)");
|
"id INTEGER PRIMARY KEY, "
|
||||||
|
"removed INTEGER, "
|
||||||
|
"taskid INTEGER, "
|
||||||
|
"starttime TEXT, "
|
||||||
|
"endtime TEXT, "
|
||||||
|
"timestamp INTEGER)");
|
||||||
mDatabase->exec("CREATE INDEX timeline_taskid_index ON timeline(taskid ASC)");
|
mDatabase->exec("CREATE INDEX timeline_taskid_index ON timeline(taskid ASC)");
|
||||||
|
|
||||||
// Tasks tree
|
// Tasks tree
|
||||||
mDatabase->exec("CREATE TABLE task (type INTEGER, removed INTEGER, "
|
mDatabase->exec("CREATE TABLE task ("
|
||||||
"id INTEGER PRIMARY KEY, parentid INTEGER, orderid INTEGER, title TEXT, html TEXT, "
|
"type INTEGER, "
|
||||||
"flags INTEGER, timestamp INTEGER)");
|
"removed INTEGER, "
|
||||||
|
"id INTEGER PRIMARY KEY, "
|
||||||
|
"parentid INTEGER, "
|
||||||
|
"orderid INTEGER, "
|
||||||
|
"title TEXT, "
|
||||||
|
"html TEXT, "
|
||||||
|
"flags INTEGER, "
|
||||||
|
"timestamp INTEGER)");
|
||||||
|
|
||||||
mDatabase->exec("CREATE INDEX task_parentid_index ON task(parentid ASC)");
|
mDatabase->exec("CREATE INDEX task_parentid_index ON task(parentid ASC)");
|
||||||
|
|
||||||
// Tasks history
|
// Tasks history
|
||||||
mDatabase->exec("CREATE TABLE history_task (removed_old INTEGER, removed_new INTEGER, "
|
mDatabase->exec("CREATE TABLE history_task ("
|
||||||
"timestamp_old INTEGER, timestamp_new INTEGER, "
|
"removed_old INTEGER, "
|
||||||
"id INTEGER PRIMARY KEY, "
|
"removed_new INTEGER, "
|
||||||
"parent_id_old INTEGER, parent_id_new INTEGER, "
|
"timestamp_old INTEGER, "
|
||||||
"order_id_old INTEGER, order_id_new INTEGER, "
|
"timestamp_new INTEGER, "
|
||||||
"diff_title TEXT, diff_html TEXT, "
|
"id INTEGER PRIMARY KEY, "
|
||||||
"flags_old INTEGER, flags_new INTEGER)");
|
"parent_id_old INTEGER, "
|
||||||
|
"parent_id_new INTEGER, "
|
||||||
|
"order_id_old INTEGER, "
|
||||||
|
"order_id_new INTEGER, "
|
||||||
|
"diff_title TEXT, "
|
||||||
|
"diff_html TEXT, "
|
||||||
|
"flags_old INTEGER, "
|
||||||
|
"flags_new INTEGER)");
|
||||||
|
|
||||||
// Attachments
|
// Attachments
|
||||||
mDatabase->exec("CREATE TABLE file (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, "
|
mDatabase->exec("CREATE TABLE file ("
|
||||||
"filename TEXT, content BLOB, orderid INTEGER, timestamp INTEGER)");
|
"id INTEGER PRIMARY KEY, "
|
||||||
|
"removed INTEGER, "
|
||||||
|
"taskid INTEGER, "
|
||||||
|
"filename TEXT, "
|
||||||
|
"content BLOB, "
|
||||||
|
"orderid INTEGER, "
|
||||||
|
"timestamp INTEGER)");
|
||||||
|
|
||||||
mDatabase->exec("CREATE TABLE history_file (id INTEGER PRIMARY KEY, "
|
mDatabase->exec("CREATE TABLE history_file ("
|
||||||
"removed_old INTEGER, removed_new INTEGER, "
|
"id INTEGER PRIMARY KEY, "
|
||||||
"taskid_old INTEGER, taskid_new INTEGER, "
|
"removed_old INTEGER, "
|
||||||
"filename_old TEXT, filename_new TEXT,"
|
"removed_new INTEGER, "
|
||||||
"content BLOB, "
|
"taskid_old INTEGER, "
|
||||||
"order_id_old INTEGER, order_id_new INTEGER, "
|
"taskid_new INTEGER, "
|
||||||
"timestamp_old INTEGER, timestamp_new INTEGER)");
|
"filename_old TEXT, "
|
||||||
|
"filename_new TEXT,"
|
||||||
|
"content BLOB, "
|
||||||
|
"order_id_old INTEGER, "
|
||||||
|
"order_id_new INTEGER, "
|
||||||
|
"timestamp_old INTEGER, "
|
||||||
|
"timestamp_new INTEGER)");
|
||||||
|
|
||||||
mDatabase->exec("CREATE INDEX file_taskid_index ON file(taskid ASC)");
|
mDatabase->exec("CREATE INDEX file_taskid_index ON file(taskid ASC)");
|
||||||
|
|
||||||
@ -319,17 +351,17 @@ bool Storage::upgradeFromVersion0()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::encryptTask(PTask task)
|
bool Storage::encryptTask(PTask /*task*/)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::encryptTaskContent(PTask task)
|
bool Storage::encryptTaskContent(PTask /*task*/)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::encryptTaskAttachment(PAttachment attachment)
|
bool Storage::encryptTaskAttachment(PAttachment /*attachment*/)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -347,8 +379,9 @@ PTask Storage::createTask(int index)
|
|||||||
if (insertQuery.exec())
|
if (insertQuery.exec())
|
||||||
{
|
{
|
||||||
PTask result(new Task());
|
PTask result(new Task());
|
||||||
result->setId(database().getLastInsertRowid());
|
result->setId(database().getLastInsertRowid())
|
||||||
result->setIndex(index);
|
.setIndex(index);
|
||||||
|
|
||||||
mTaskModelIdMap[result->modelId()] = result;
|
mTaskModelIdMap[result->modelId()] = result;
|
||||||
mTaskIdMap[result->id()] = result;
|
mTaskIdMap[result->id()] = result;
|
||||||
if (index > mTopTasks.size())
|
if (index > mTopTasks.size())
|
||||||
@ -359,8 +392,8 @@ PTask Storage::createTask(int index)
|
|||||||
// Assign new indexes for top tasks
|
// Assign new indexes for top tasks
|
||||||
for (int i=0; i<mTopTasks.size(); i++)
|
for (int i=0; i<mTopTasks.size(); i++)
|
||||||
{
|
{
|
||||||
mTopTasks[i]->setIndex(i);
|
mTopTasks[i]->setIndex(i)
|
||||||
mTopTasks[i]->save();
|
.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -369,7 +402,7 @@ PTask Storage::createTask(int index)
|
|||||||
return PTask();
|
return PTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
PTask Storage::createTask(PTask parent, int index)
|
PTask Storage::createTask(const PTask& parent, int index)
|
||||||
{
|
{
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return createTask(index);
|
return createTask(index);
|
||||||
@ -394,8 +427,8 @@ PTask Storage::createTask(PTask parent, int index)
|
|||||||
parent->children().insert(parent->children().begin() + index, result);
|
parent->children().insert(parent->children().begin() + index, result);
|
||||||
for (int i=0; i<parent->children().size(); i++)
|
for (int i=0; i<parent->children().size(); i++)
|
||||||
{
|
{
|
||||||
parent->children()[i]->setIndex(i);
|
parent->children()[i]->setIndex(i)
|
||||||
parent->children()[i]->save();
|
.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,8 +503,8 @@ bool Storage::moveTask(PTask task, PTask newParent, int indexToInsert)
|
|||||||
|
|
||||||
for (int i=0; i<topOfTaskTree().size(); i++)
|
for (int i=0; i<topOfTaskTree().size(); i++)
|
||||||
{
|
{
|
||||||
topOfTaskTree()[i]->setIndex(i);
|
topOfTaskTree()[i]->setIndex(i)
|
||||||
topOfTaskTree()[i]->save();
|
.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,6 +537,15 @@ void Storage::saveSingleTask(PTask task)
|
|||||||
task->save();
|
task->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Storage::loadTaskRecord(Task& t, SQLite::Statement& q)
|
||||||
|
{
|
||||||
|
t.mId = q.getColumn(0).getInt64();
|
||||||
|
t.mTitle = q.getColumn(1).getText();
|
||||||
|
t.mIndex = q.getColumn(2).getInt();
|
||||||
|
t.mFlags = q.getColumn(3).getInt();
|
||||||
|
t.mAttachmentCount = q.getColumn(4).getInt();
|
||||||
|
}
|
||||||
|
|
||||||
void Storage::loadTaskTree()
|
void Storage::loadTaskTree()
|
||||||
{
|
{
|
||||||
mTopTasks.clear();
|
mTopTasks.clear();
|
||||||
@ -513,7 +555,7 @@ void Storage::loadTaskTree()
|
|||||||
while(q.executeStep())
|
while(q.executeStep())
|
||||||
{
|
{
|
||||||
PTask t(new Task());
|
PTask t(new Task());
|
||||||
t->load(q);
|
loadTaskRecord(*t, q);
|
||||||
t->setIndex(currentIndex++);
|
t->setIndex(currentIndex++);
|
||||||
mTaskModelIdMap[t->modelId()] = t;
|
mTaskModelIdMap[t->modelId()] = t;
|
||||||
mTaskIdMap[t->id()] = t;
|
mTaskIdMap[t->id()] = t;
|
||||||
@ -532,9 +574,10 @@ void Storage::loadTaskChildren(PTask task)
|
|||||||
while (q.executeStep())
|
while (q.executeStep())
|
||||||
{
|
{
|
||||||
PTask t(new Task());
|
PTask t(new Task());
|
||||||
t->load(q);
|
loadTaskRecord(*t, q);
|
||||||
t->setIndex(currentIndex++);
|
t->setIndex(currentIndex++)
|
||||||
t->setParent(task, false);
|
.setParent(task, false);
|
||||||
|
|
||||||
loadTaskChildren(t);
|
loadTaskChildren(t);
|
||||||
mTaskModelIdMap[t->modelId()] = t;
|
mTaskModelIdMap[t->modelId()] = t;
|
||||||
mTaskIdMap[t->id()] = t;
|
mTaskIdMap[t->id()] = t;
|
||||||
@ -580,10 +623,10 @@ void Storage::loadAttachments(PTask task, AttachmentArray& output)
|
|||||||
while (q.executeStep())
|
while (q.executeStep())
|
||||||
{
|
{
|
||||||
PAttachment att(new Attachment());
|
PAttachment att(new Attachment());
|
||||||
att->setId(q.getColumn(0).getInt64());
|
att->setId(q.getColumn(0).getInt64())
|
||||||
att->setFilename(q.getColumn(1).getText());
|
.setFilename(q.getColumn(1).getText())
|
||||||
att->setTaskId(task->id());
|
.setTaskId(task->id())
|
||||||
att->setIndex(q.getColumn(2).getInt());
|
.setIndex(q.getColumn(2).getInt());
|
||||||
output.push_back(att);
|
output.push_back(att);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,6 +645,114 @@ void Storage::undeleteAttachment(PAttachment att)
|
|||||||
q.exec();
|
q.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id Storage::saveMetadata(const Attachment &a)
|
||||||
|
{
|
||||||
|
if (a.mId)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "update file set filename = :filename, orderid = :orderid where id = :id");
|
||||||
|
q.bind(":filename", a.mFilename.toStdString().c_str());
|
||||||
|
q.bind(":orderid", a.mIndex);
|
||||||
|
q.bind(":id", (sqlite3_int64)a.mId);
|
||||||
|
|
||||||
|
if (q.exec())
|
||||||
|
return a.mId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "insert into file (filename, taskid, orderid, removed) values(:filename, :taskid, :orderid, 0)");
|
||||||
|
q.bind(":filename", a.mFilename.toStdString().c_str());
|
||||||
|
q.bind(":taskid", (sqlite3_int64)a.mTaskId);
|
||||||
|
q.bind(":orderid", a.mIndex);
|
||||||
|
if (q.exec())
|
||||||
|
{
|
||||||
|
return Storage::instance().database().getLastInsertRowid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Id(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::saveContent(const Attachment &a, const QByteArray& content)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "update file set content = :content where id = :id");
|
||||||
|
q.bind(":content", content.data(), content.size());
|
||||||
|
q.bind(":id", (sqlite3_int64)a.mId);
|
||||||
|
if (q.exec())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Storage::loadContent(const Attachment &a)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "select content from file where id = :id");
|
||||||
|
q.bind(":id", (sqlite3_int64)a.mId);
|
||||||
|
if (q.executeStep())
|
||||||
|
return QByteArray((const char*)q.getColumn(0).getBlob(), q.getColumn(0).size());
|
||||||
|
else
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
Id Storage::saveTimeRecord(const TimeRecord &r)
|
||||||
|
{
|
||||||
|
if (!r.id())
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "insert into timeline(id, starttime, endtime, taskid, removed) values (NULL, :starttime, :endtime, :taskid, :removed)");
|
||||||
|
|
||||||
|
q.bind(":starttime", helper::chrono::timeToStr(r.startTime()));
|
||||||
|
q.bind(":endtime", helper::chrono::timeToStr(r.endTime()));
|
||||||
|
q.bind(":taskid", static_cast<sqlite3_int64>(r.taskId()));
|
||||||
|
q.bind(":removed", 0);
|
||||||
|
if (q.exec())
|
||||||
|
return Storage::instance().database().getLastInsertRowid();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(),
|
||||||
|
"update timeline set starttime = :starttime, endtime = :endtime, taskid = :taskid, removed = 0 where id = :id");
|
||||||
|
q.bind(":starttime", helper::chrono::timeToStr(r.startTime()));
|
||||||
|
q.bind(":endtime", helper::chrono::timeToStr(r.endTime()));
|
||||||
|
q.bind(":taskid", static_cast<sqlite3_int64>(r.taskId()));
|
||||||
|
q.bind(":id", static_cast<sqlite3_int64>(r.id()));
|
||||||
|
if (q.exec())
|
||||||
|
return r.id();
|
||||||
|
}
|
||||||
|
return (Id)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::deleteTimeRecord(const TimeRecord &r)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "update timeline set removed = 1 where id = :id");
|
||||||
|
q.bind(":id", static_cast<sqlite3_int64>(r.id()));
|
||||||
|
q.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::loadTimeLine(TimeLine& l)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "select id, starttime, endtime from timeline where (taskid = :taskid) and ((removed is null) or (removed != 1)) order by id asc");
|
||||||
|
q.bind(":taskid", static_cast<sqlite3_int64>(l.taskId()));
|
||||||
|
while (q.executeStep())
|
||||||
|
{
|
||||||
|
time_t start = helper::chrono::strToTime(q.getColumn(1).getText());
|
||||||
|
time_t stop = helper::chrono::strToTime(q.getColumn(2).getText());
|
||||||
|
|
||||||
|
TimeRecord tr;
|
||||||
|
tr.setId(q.getColumn(0).getInt64())
|
||||||
|
.setStartTime(start)
|
||||||
|
.setEndTime(stop)
|
||||||
|
.setTaskId(l.taskId());
|
||||||
|
l.data().push_back(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort time intervals
|
||||||
|
l.sortData();
|
||||||
|
|
||||||
|
// Find current total time length
|
||||||
|
l.mTotalTime = l.findTotalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::saveTimeLime(const TimeLine& l)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Storage& Storage::instance()
|
Storage& Storage::instance()
|
||||||
{
|
{
|
||||||
@ -610,7 +761,7 @@ Storage& Storage::instance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Storage::deleteTask(PTask task, DeleteOption option)
|
void Storage::deleteTask(const PTask& task, DeleteOption option)
|
||||||
{
|
{
|
||||||
if (option != DeleteOption_FromParent)
|
if (option != DeleteOption_FromParent)
|
||||||
{
|
{
|
||||||
@ -651,7 +802,7 @@ void Storage::deleteTask(PTask task, DeleteOption option)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Storage::undeleteTask(PTask task)
|
void Storage::undeleteTask(const PTask& task)
|
||||||
{
|
{
|
||||||
SQLite::Statement q(database(), "update task set removed = 0 where id = :id");
|
SQLite::Statement q(database(), "update task set removed = 0 where id = :id");
|
||||||
q.bind(":id", (sqlite3_int64)task->id());
|
q.bind(":id", (sqlite3_int64)task->id());
|
||||||
@ -670,7 +821,7 @@ void Storage::undeleteTask(PTask task)
|
|||||||
mTaskIdMap[task->id()] = task;
|
mTaskIdMap[task->id()] = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Storage::removeTask(PTask task)
|
void Storage::removeTask(const PTask& task)
|
||||||
{
|
{
|
||||||
auto taskModelIter = mTaskModelIdMap.find(task->modelId());
|
auto taskModelIter = mTaskModelIdMap.find(task->modelId());
|
||||||
if (taskModelIter != mTaskModelIdMap.end())
|
if (taskModelIter != mTaskModelIdMap.end())
|
||||||
@ -681,3 +832,69 @@ void Storage::removeTask(PTask task)
|
|||||||
mTaskIdMap.erase(taskIter);
|
mTaskIdMap.erase(taskIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Storage::loadTaskContent(Task& task)
|
||||||
|
{
|
||||||
|
SQLite::Statement htmlQuery(Storage::instance().database(), "select html from task where id = :id");
|
||||||
|
htmlQuery.bind(":id", (sqlite3_int64)task.mId);
|
||||||
|
if (htmlQuery.executeStep())
|
||||||
|
{
|
||||||
|
task.mHtml = htmlQuery.getColumn(0).getText();
|
||||||
|
task.mHtmlLoaded = true;
|
||||||
|
task.mHtmlModified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!task.mTimeLine)
|
||||||
|
{
|
||||||
|
task.mTimeLine = PTimeLine(new TimeLine());
|
||||||
|
task.mTimeLine->setTaskId(task.mId);
|
||||||
|
task.mTimeLine->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::saveTask(const Task& task, SaveOptions options)
|
||||||
|
{
|
||||||
|
const Task& t = task;
|
||||||
|
|
||||||
|
if (!t.mTitleModified && !t.mHtmlModified && !t.mIndexModified && !t.mParentModified && options == Save_Automatic)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* queryText = nullptr;
|
||||||
|
// Minimize changes to DB
|
||||||
|
if (t.mTitleModified && t.mHtmlModified)
|
||||||
|
queryText = "update task set parentid = :parentid, flags = :flags, title = :title, html = :html, orderid = :orderid where id = :id";
|
||||||
|
else
|
||||||
|
if (t.mTitleModified)
|
||||||
|
queryText = "update task set parentid = :parentid, flags = :flags, title = :title, orderid = :orderid where id = :id";
|
||||||
|
else
|
||||||
|
if (t.mHtmlModified)
|
||||||
|
queryText = "update task set parentid = :parentid, flags = :flags, html = :html, orderid = :orderid where id = :id";
|
||||||
|
else
|
||||||
|
queryText = "update task set parentid = :parentid, flags = :flags, orderid = :orderid where id = :id";
|
||||||
|
|
||||||
|
SQLite::Statement q(Storage::instance().database(), queryText);
|
||||||
|
if (t.mParent)
|
||||||
|
q.bind(":parentid", (sqlite3_int64)t.mParent->id());
|
||||||
|
else
|
||||||
|
q.bind(":parentid");
|
||||||
|
|
||||||
|
q.bind(":flags", t.mFlags);
|
||||||
|
|
||||||
|
if (t.mTitleModified)
|
||||||
|
q.bind(":title", t.mTitle.toStdString());
|
||||||
|
if (t.mHtmlModified)
|
||||||
|
q.bind(":html", t.mHtml.toStdString());
|
||||||
|
|
||||||
|
q.bind(":id", (sqlite3_int64)t.mId);
|
||||||
|
q.bind(":orderid", t.mIndex);
|
||||||
|
q.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Storage::findAttachmentCountOnTask(const Task &t)
|
||||||
|
{
|
||||||
|
SQLite::Statement q(Storage::instance().database(), "select count(*) from file where (taskid = :taskid) and ((removed = 0) or (removed is null))");
|
||||||
|
q.bind(":taskid", (sqlite3_int64)t.id());
|
||||||
|
if (q.executeStep())
|
||||||
|
return q.getColumn(0).getInt();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
157
client/storage.h
157
client/storage.h
@ -9,86 +9,117 @@
|
|||||||
class Storage
|
class Storage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Storage();
|
Storage();
|
||||||
~Storage();
|
~Storage();
|
||||||
|
|
||||||
QString path();
|
QString path();
|
||||||
void setPath(const QString& path);
|
void setPath(const QString& path);
|
||||||
QString key();
|
QString key();
|
||||||
void setKey(const QString& key);
|
void setKey(const QString& key);
|
||||||
|
|
||||||
SQLite::Database& database();
|
SQLite::Database& database();
|
||||||
|
|
||||||
// New database. Returns true or false depending on success of call.
|
// New database. Returns true or false depending on success of call.
|
||||||
bool create();
|
bool create();
|
||||||
|
|
||||||
// Open database, preload task tree. Returns true or false depending on success of operation.
|
// Open database, preload task tree. Returns true or false depending on success of operation.
|
||||||
bool open();
|
bool open();
|
||||||
|
|
||||||
// Close database
|
// Close database
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
// Ensure database is latest version
|
// Ensure database is latest version
|
||||||
bool upgrade();
|
bool upgrade();
|
||||||
|
|
||||||
PTask createTask(int index);
|
PTask createTask(int index);
|
||||||
PTask createTask(PTask parent, int index);
|
PTask createTask(const PTask& parent, int index);
|
||||||
PTask loadTask(Task::Id id, PTask parent);
|
// PTask loadTask(Task::Id id, PTask parent);
|
||||||
|
|
||||||
// Remove task from database
|
// Remove task from database
|
||||||
enum DeleteOption
|
enum DeleteOption
|
||||||
{
|
{
|
||||||
DeleteOption_Total,
|
DeleteOption_Total,
|
||||||
DeleteOption_FromParentAndHash,
|
DeleteOption_FromParentAndHash,
|
||||||
DeleteOption_FromParent
|
DeleteOption_FromParent
|
||||||
};
|
};
|
||||||
|
|
||||||
void deleteTask(PTask task, DeleteOption option);
|
void deleteTask(const PTask& task, DeleteOption option);
|
||||||
|
|
||||||
// Undelete task
|
// Undelete task
|
||||||
void undeleteTask(PTask task);
|
void undeleteTask(const PTask& task);
|
||||||
|
|
||||||
// Remove task from internal dictionaries - it makes task unadressable by its id/model id
|
// Remove task from internal dictionaries - it makes task unadressable by its id/model id
|
||||||
void removeTask(PTask task);
|
void removeTask(const PTask& task);
|
||||||
|
|
||||||
enum Depth
|
void loadTaskContent(Task& task);
|
||||||
{
|
void loadTaskMetadata(Task& task);
|
||||||
depthSingleTask,
|
|
||||||
depthRecursive
|
|
||||||
};
|
|
||||||
void saveTask(PTask task, Depth depth);
|
|
||||||
bool moveTask(PTask task, PTask newParent, int indexToInsert);
|
|
||||||
bool isOpened();
|
|
||||||
void save();
|
|
||||||
TaskArray& topOfTaskTree();
|
|
||||||
PTask findTaskByModelId(Task::ModelId id);
|
|
||||||
PTask findTaskById(Task::Id id);
|
|
||||||
int findTaskIndexInParent(PTask task);
|
|
||||||
void loadAttachments(PTask task, AttachmentArray& output);
|
|
||||||
void deleteAttachment(PAttachment att);
|
|
||||||
void undeleteAttachment(PAttachment att);
|
|
||||||
|
|
||||||
static Storage& instance();
|
// Save changes in single task
|
||||||
|
enum SaveOptions
|
||||||
|
{
|
||||||
|
Save_Automatic,
|
||||||
|
Save_Forced
|
||||||
|
};
|
||||||
|
void saveTask(const Task& task, SaveOptions options = Save_Automatic);
|
||||||
|
|
||||||
|
// Save Task hierarchy
|
||||||
|
enum Depth
|
||||||
|
{
|
||||||
|
depthSingleTask,
|
||||||
|
depthRecursive
|
||||||
|
};
|
||||||
|
void saveTask(PTask task, Depth depth);
|
||||||
|
|
||||||
|
int findAttachmentCountOnTask(const Task& t);
|
||||||
|
|
||||||
|
// Move task
|
||||||
|
bool moveTask(PTask task, PTask newParent, int indexToInsert);
|
||||||
|
|
||||||
|
bool isOpened();
|
||||||
|
void save();
|
||||||
|
|
||||||
|
TaskArray& topOfTaskTree();
|
||||||
|
PTask findTaskByModelId(Task::ModelId id);
|
||||||
|
PTask findTaskById(Task::Id id);
|
||||||
|
int findTaskIndexInParent(PTask task);
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
void loadAttachments(PTask task, AttachmentArray& output);
|
||||||
|
void deleteAttachment(PAttachment att);
|
||||||
|
void undeleteAttachment(PAttachment att);
|
||||||
|
Id saveMetadata(const Attachment& attachment);
|
||||||
|
void saveContent(const Attachment& attachment, const QByteArray& content);
|
||||||
|
QByteArray loadContent(const Attachment& attachment);
|
||||||
|
|
||||||
|
// Timeline
|
||||||
|
Id saveTimeRecord(const TimeRecord& r);
|
||||||
|
void deleteTimeRecord(const TimeRecord& r);
|
||||||
|
|
||||||
|
void loadTimeLine(TimeLine& l);
|
||||||
|
void saveTimeLime(const TimeLine& l);
|
||||||
|
|
||||||
|
static Storage& instance();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString mPath, mKey;
|
QString mPath, mKey;
|
||||||
QSharedPointer<SQLite::Database> mDatabase;
|
QSharedPointer<SQLite::Database> mDatabase;
|
||||||
TaskArray mTopTasks;
|
TaskArray mTopTasks;
|
||||||
typedef QMap<Task::ModelId, PTask> TaskModelIdMap;
|
typedef QMap<Task::ModelId, PTask> TaskModelIdMap;
|
||||||
TaskModelIdMap mTaskModelIdMap;
|
TaskModelIdMap mTaskModelIdMap;
|
||||||
typedef QMap<Task::Id, PTask> TaskIdMap;
|
typedef QMap<Task::Id, PTask> TaskIdMap;
|
||||||
TaskIdMap mTaskIdMap;
|
TaskIdMap mTaskIdMap;
|
||||||
|
|
||||||
TaskArray mTaskToUpgrade;
|
TaskArray mTaskToUpgrade;
|
||||||
|
|
||||||
bool hasTable(const QString& tablename);
|
bool hasTable(const QString& tablename);
|
||||||
void saveSingleTask(PTask task);
|
void saveSingleTask(PTask task);
|
||||||
void loadTaskTree();
|
void loadTaskRecord(Task& t, SQLite::Statement& q);
|
||||||
void loadTaskChildren(PTask task);
|
void loadTaskTree();
|
||||||
bool upgradeFromVersion0();
|
void loadTaskChildren(PTask task);
|
||||||
bool encryptTask(PTask task);
|
bool upgradeFromVersion0();
|
||||||
bool encryptTaskContent(PTask task);
|
bool encryptTask(PTask task);
|
||||||
bool encryptTaskAttachment(PAttachment attachment);
|
bool encryptTaskContent(PTask task);
|
||||||
|
bool encryptTaskAttachment(PAttachment attachment);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STORAGE_H
|
#endif // STORAGE_H
|
||||||
|
|||||||
316
client/task.cpp
316
client/task.cpp
@ -86,9 +86,10 @@ time_t TimeRecord::endTime() const
|
|||||||
return mEndTime;
|
return mEndTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setEndTime(const time_t &endTime)
|
TimeRecord& TimeRecord::setEndTime(const time_t &endTime)
|
||||||
{
|
{
|
||||||
mEndTime = endTime;
|
mEndTime = endTime;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t TimeRecord::startTime() const
|
time_t TimeRecord::startTime() const
|
||||||
@ -96,9 +97,10 @@ time_t TimeRecord::startTime() const
|
|||||||
return mStartTime;
|
return mStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setStartTime(const time_t &startTime)
|
TimeRecord& TimeRecord::setStartTime(const time_t &startTime)
|
||||||
{
|
{
|
||||||
mStartTime = startTime;
|
mStartTime = startTime;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimeRecord::length()
|
int TimeRecord::length()
|
||||||
@ -111,9 +113,10 @@ Id TimeRecord::id() const
|
|||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setId(Id id)
|
TimeRecord& TimeRecord::setId(Id id)
|
||||||
{
|
{
|
||||||
mId = id;
|
mId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id TimeRecord::taskId() const
|
Id TimeRecord::taskId() const
|
||||||
@ -121,9 +124,10 @@ Id TimeRecord::taskId() const
|
|||||||
return mTaskId;
|
return mTaskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setTaskId(Id id)
|
TimeRecord& TimeRecord::setTaskId(Id id)
|
||||||
{
|
{
|
||||||
mTaskId = id;
|
mTaskId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldId TimeRecord::worldId() const
|
WorldId TimeRecord::worldId() const
|
||||||
@ -131,41 +135,22 @@ WorldId TimeRecord::worldId() const
|
|||||||
return mWorldId;
|
return mWorldId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::setWorldId(const WorldId& id)
|
TimeRecord& TimeRecord::setWorldId(const WorldId& id)
|
||||||
{
|
{
|
||||||
mWorldId = id;
|
mWorldId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::save()
|
void TimeRecord::save()
|
||||||
{
|
{
|
||||||
if (!mId)
|
auto id = Storage::instance().saveTimeRecord(*this);
|
||||||
{
|
if (id)
|
||||||
SQLite::Statement q(Storage::instance().database(), "insert into timeline(id, starttime, endtime, taskid, removed) values (NULL, :starttime, :endtime, :taskid, :removed)");
|
mId = id;
|
||||||
|
|
||||||
q.bind(":starttime", helper::chrono::timeToStr(mStartTime));
|
|
||||||
q.bind(":endtime", helper::chrono::timeToStr(mEndTime));
|
|
||||||
q.bind(":taskid", static_cast<sqlite3_int64>(mTaskId));
|
|
||||||
q.bind(":removed", 0);
|
|
||||||
if (q.exec())
|
|
||||||
mId = Storage::instance().database().getLastInsertRowid();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SQLite::Statement q(Storage::instance().database(),
|
|
||||||
"update timeline set starttime = :starttime, endtime = :endtime, taskid = :taskid, removed = 0 where id = :id");
|
|
||||||
q.bind(":starttime", helper::chrono::timeToStr(mStartTime));
|
|
||||||
q.bind(":endtime", helper::chrono::timeToStr(mEndTime));
|
|
||||||
q.bind(":taskid", static_cast<sqlite3_int64>(mTaskId));
|
|
||||||
q.bind(":id", static_cast<sqlite3_int64>(mId));
|
|
||||||
q.exec();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRecord::deleteRecord()
|
void TimeRecord::deleteRecord()
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "update timeline set removed = 1 where id = :id");
|
Storage::instance().deleteTimeRecord(*this);
|
||||||
q.bind(":id", static_cast<sqlite3_int64>(mId));
|
|
||||||
q.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- TimeLine --------------------
|
// -------------------- TimeLine --------------------
|
||||||
@ -218,10 +203,10 @@ void TimeLine::start()
|
|||||||
TimeRecord* TimeLine::makeNewRecord(time_t beginTime, time_t endTime)
|
TimeRecord* TimeLine::makeNewRecord(time_t beginTime, time_t endTime)
|
||||||
{
|
{
|
||||||
TimeRecord tr;
|
TimeRecord tr;
|
||||||
tr.setStartTime(beginTime);
|
tr.setStartTime(beginTime)
|
||||||
tr.setEndTime(endTime);
|
.setEndTime(endTime)
|
||||||
tr.setTaskId(mTaskId);
|
.setTaskId(mTaskId)
|
||||||
tr.save();
|
.save();
|
||||||
|
|
||||||
mData.push_back(tr);
|
mData.push_back(tr);
|
||||||
Id intervalId = tr.id();
|
Id intervalId = tr.id();
|
||||||
@ -388,11 +373,13 @@ 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() - 1);
|
iter->setEndTime(interval.startTime() - 1)
|
||||||
iter->save();
|
.save();
|
||||||
toInsert.setStartTime(interval.endTime() + 1);
|
|
||||||
|
toInsert.setStartTime(interval.endTime() + 1)
|
||||||
|
.save();
|
||||||
mData.insert(++iter, toInsert);
|
mData.insert(++iter, toInsert);
|
||||||
toInsert.save();
|
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -407,8 +394,8 @@ 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() - 1);
|
iter->setEndTime(interval.startTime() - 1)
|
||||||
iter->save();
|
.save();
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -425,7 +412,10 @@ void TimeLine::cutInterval(const TimeRecord& interval)
|
|||||||
[=] (const TimeRecord& tr)
|
[=] (const TimeRecord& tr)
|
||||||
{ return tr.id() == interval.id();});
|
{ return tr.id() == interval.id();});
|
||||||
if (iter != mData.end())
|
if (iter != mData.end())
|
||||||
|
{
|
||||||
|
Storage::instance().deleteTimeRecord(*iter);
|
||||||
mData.erase(iter);
|
mData.erase(iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,8 +455,8 @@ void TimeLine::flush(bool saveToDb, time_t currentUtc)
|
|||||||
TimeRecord* tr = hasTimePoint(currentUtc);
|
TimeRecord* tr = hasTimePoint(currentUtc);
|
||||||
if (tr && tr != mActiveTimeRecord)
|
if (tr && tr != mActiveTimeRecord)
|
||||||
{
|
{
|
||||||
mActiveTimeRecord->setEndTime(currentUtc);
|
mActiveTimeRecord->setEndTime(currentUtc)
|
||||||
mActiveTimeRecord->save();
|
.save();
|
||||||
mActiveTimeRecord = nullptr;
|
mActiveTimeRecord = nullptr;
|
||||||
}
|
}
|
||||||
if (saveToDb && mActiveTimeRecord)
|
if (saveToDb && mActiveTimeRecord)
|
||||||
@ -486,26 +476,7 @@ void TimeLine::flush(bool saveToDb, time_t currentUtc)
|
|||||||
|
|
||||||
void TimeLine::load()
|
void TimeLine::load()
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "select id, starttime, endtime from timeline where (taskid = :taskid) and ((removed is null) or (removed != 1)) order by id asc");
|
Storage::instance().loadTimeLine(*this);
|
||||||
q.bind(":taskid", static_cast<sqlite3_int64>(mTaskId));
|
|
||||||
while (q.executeStep())
|
|
||||||
{
|
|
||||||
time_t start = helper::chrono::strToTime(q.getColumn(1).getText());
|
|
||||||
time_t stop = helper::chrono::strToTime(q.getColumn(2).getText());
|
|
||||||
|
|
||||||
TimeRecord tr;
|
|
||||||
tr.setId(q.getColumn(0).getInt64());
|
|
||||||
tr.setStartTime(start);
|
|
||||||
tr.setEndTime(stop);
|
|
||||||
tr.setTaskId(mTaskId);
|
|
||||||
mData.push_back(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort time intervals
|
|
||||||
sortData();
|
|
||||||
|
|
||||||
// Find current total time length
|
|
||||||
mTotalTime = findTotalTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeLine::save()
|
void TimeLine::save()
|
||||||
@ -518,9 +489,10 @@ Id TimeLine::taskId()
|
|||||||
return mTaskId;
|
return mTaskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeLine::setTaskId(Id id)
|
TimeLine& TimeLine::setTaskId(Id id)
|
||||||
{
|
{
|
||||||
mTaskId = id;
|
mTaskId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeArray& TimeLine::data()
|
TimeArray& TimeLine::data()
|
||||||
@ -668,10 +640,10 @@ int TimeLine::getTime(int year, int month, int day, std::vector<TimeRecord>* int
|
|||||||
if (intervals)
|
if (intervals)
|
||||||
{
|
{
|
||||||
TimeRecord resultingRecord;
|
TimeRecord resultingRecord;
|
||||||
resultingRecord.setStartTime(dayBegin);
|
resultingRecord.setStartTime(dayBegin)
|
||||||
resultingRecord.setEndTime(dayEnd);
|
.setEndTime(dayEnd)
|
||||||
resultingRecord.setId(tr.id());
|
.setId(tr.id())
|
||||||
resultingRecord.setTaskId(tr.taskId());
|
.setTaskId(tr.taskId());
|
||||||
intervals->push_back(resultingRecord);
|
intervals->push_back(resultingRecord);
|
||||||
}
|
}
|
||||||
result++;
|
result++;
|
||||||
@ -822,26 +794,17 @@ Task::Task()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task::~Task()
|
Task::~Task()
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void Task::load(SQLite::Statement &q)
|
|
||||||
{
|
|
||||||
mId = q.getColumn(0).getInt64();
|
|
||||||
mTitle = q.getColumn(1).getText();
|
|
||||||
mIndex = q.getColumn(2).getInt();
|
|
||||||
mFlags = q.getColumn(3).getInt();
|
|
||||||
mAttachmentCount = q.getColumn(4).getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
Task::Id Task::id() const
|
Task::Id Task::id() const
|
||||||
{
|
{
|
||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setId(Id id)
|
Task& Task::setId(Id id)
|
||||||
{
|
{
|
||||||
mId = id;
|
mId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Id Task::parentId() const
|
Task::Id Task::parentId() const
|
||||||
@ -849,13 +812,14 @@ Task::Id Task::parentId() const
|
|||||||
return mParentId;
|
return mParentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setParentId(Id id)
|
Task& Task::setParentId(Id id)
|
||||||
{
|
{
|
||||||
if (mParentId != id)
|
if (mParentId != id)
|
||||||
{
|
{
|
||||||
mParentModified = true;
|
mParentModified = true;
|
||||||
mParentId = id;
|
mParentId = id;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldId Task::worldId() const
|
WorldId Task::worldId() const
|
||||||
@ -863,9 +827,10 @@ WorldId Task::worldId() const
|
|||||||
return mWorldId;
|
return mWorldId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setWorldId(const WorldId& id)
|
Task& Task::setWorldId(const WorldId& id)
|
||||||
{
|
{
|
||||||
mWorldId = id;
|
mWorldId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::ModelId Task::modelId() const
|
Task::ModelId Task::modelId() const
|
||||||
@ -873,9 +838,10 @@ Task::ModelId Task::modelId() const
|
|||||||
return mModelId;
|
return mModelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setModelId(ModelId id)
|
Task& Task::setModelId(ModelId id)
|
||||||
{
|
{
|
||||||
mModelId = id;
|
mModelId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::index() const
|
int Task::index() const
|
||||||
@ -883,7 +849,7 @@ int Task::index() const
|
|||||||
return mIndex;
|
return mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setIndex(int index, bool modified)
|
Task& Task::setIndex(int index, bool modified)
|
||||||
{
|
{
|
||||||
if (index != mIndex)
|
if (index != mIndex)
|
||||||
{
|
{
|
||||||
@ -891,6 +857,7 @@ void Task::setIndex(int index, bool modified)
|
|||||||
mIndexModified = true;
|
mIndexModified = true;
|
||||||
mIndex = index;
|
mIndex = index;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Task::html() const
|
QString Task::html() const
|
||||||
@ -898,13 +865,14 @@ QString Task::html() const
|
|||||||
return mHtml;
|
return mHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setHtml(const QString &html)
|
Task& Task::setHtml(const QString &html)
|
||||||
{
|
{
|
||||||
if (mHtml != html)
|
if (mHtml != html)
|
||||||
{
|
{
|
||||||
mHtml = html;
|
mHtml = html;
|
||||||
mHtmlModified = true;
|
mHtmlModified = true;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Task::title() const
|
QString Task::title() const
|
||||||
@ -912,7 +880,7 @@ QString Task::title() const
|
|||||||
return mTitle;
|
return mTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setTitle(const QString &title, bool modified)
|
Task& Task::setTitle(const QString &title, bool modified)
|
||||||
{
|
{
|
||||||
if (mTitle != title)
|
if (mTitle != title)
|
||||||
{
|
{
|
||||||
@ -920,61 +888,20 @@ void Task::setTitle(const QString &title, bool modified)
|
|||||||
if (modified)
|
if (modified)
|
||||||
mTitleModified = true;
|
mTitleModified = true;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::save(SaveOptions options)
|
void Task::save()
|
||||||
{
|
{
|
||||||
if (!mTitleModified && !mHtmlModified && !mIndexModified && !mParentModified && options == Save_Automatic)
|
Storage::instance().saveTask(*this);
|
||||||
return;
|
|
||||||
|
|
||||||
const char* queryText = NULL;
|
|
||||||
|
|
||||||
if (mTitleModified && mHtmlModified)
|
|
||||||
queryText = "update task set parentid = :parentid, flags = :flags, title = :title, html = :html, orderid = :orderid where id = :id";
|
|
||||||
else
|
|
||||||
if (mTitleModified)
|
|
||||||
queryText = "update task set parentid = :parentid, flags = :flags, title = :title, orderid = :orderid where id = :id";
|
|
||||||
else
|
|
||||||
if (mHtmlModified)
|
|
||||||
queryText = "update task set parentid = :parentid, flags = :flags, html = :html, orderid = :orderid where id = :id";
|
|
||||||
else
|
|
||||||
queryText = "update task set parentid = :parentid, flags = :flags, orderid = :orderid where id = :id";
|
|
||||||
|
|
||||||
SQLite::Statement q(Storage::instance().database(), queryText);
|
|
||||||
if (mParent)
|
|
||||||
q.bind(":parentid", (sqlite3_int64)mParent->id());
|
|
||||||
else
|
|
||||||
q.bind(":parentid");
|
|
||||||
|
|
||||||
q.bind(":flags", mFlags);
|
|
||||||
|
|
||||||
if (mTitleModified)
|
|
||||||
q.bind(":title", mTitle.toStdString());
|
|
||||||
if (mHtmlModified)
|
|
||||||
q.bind(":html", mHtml.toStdString());
|
|
||||||
|
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
|
||||||
q.bind(":orderid", mIndex);
|
|
||||||
q.exec();
|
|
||||||
mIndexModified = mTitleModified = mHtmlModified = false;
|
mIndexModified = mTitleModified = mHtmlModified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void Task::load()
|
void Task::saveAnyway()
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "select parentid, title, html, orderid from task where (id = :id) and (type = 0)");
|
Storage::instance().saveTask(*this, Storage::Save_Forced);
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
mIndexModified = mTitleModified = mHtmlModified = false;
|
||||||
if (q.executeStep())
|
}
|
||||||
{
|
|
||||||
mParentId = q.getColumn(0).getInt64();
|
|
||||||
mTitle = q.getColumn(1).getText();
|
|
||||||
mHtml = q.getColumn(2).getText();
|
|
||||||
mIndex = q.getColumn(3).getInt();
|
|
||||||
}
|
|
||||||
mTitleModified = mHtmlModified = false;
|
|
||||||
mHtmlLoaded = true;
|
|
||||||
|
|
||||||
checkAttachments();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QString Task::path() const
|
QString Task::path() const
|
||||||
{
|
{
|
||||||
@ -990,7 +917,7 @@ PTask Task::parent() const
|
|||||||
return mParent;
|
return mParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setParent(PTask task, bool modified)
|
Task& Task::setParent(PTask task, bool modified)
|
||||||
{
|
{
|
||||||
if (mParent != task)
|
if (mParent != task)
|
||||||
{
|
{
|
||||||
@ -1002,6 +929,7 @@ void Task::setParent(PTask task, bool modified)
|
|||||||
if (modified)
|
if (modified)
|
||||||
mTitleModified = true; // To force save()
|
mTitleModified = true; // To force save()
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskArray& Task::children()
|
TaskArray& Task::children()
|
||||||
@ -1011,21 +939,7 @@ TaskArray& Task::children()
|
|||||||
|
|
||||||
void Task::loadContent()
|
void Task::loadContent()
|
||||||
{
|
{
|
||||||
SQLite::Statement htmlQuery(Storage::instance().database(), "select html from task where id = :id");
|
Storage::instance().loadTaskContent(*this);
|
||||||
htmlQuery.bind(":id", (sqlite3_int64)mId);
|
|
||||||
if (htmlQuery.executeStep())
|
|
||||||
{
|
|
||||||
mHtml = htmlQuery.getColumn(0).getText();
|
|
||||||
mHtmlLoaded = true;
|
|
||||||
mHtmlModified = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mTimeLine)
|
|
||||||
{
|
|
||||||
mTimeLine = PTimeLine(new TimeLine());
|
|
||||||
mTimeLine->setTaskId(mId);
|
|
||||||
mTimeLine->load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::isContentLoaded() const
|
bool Task::isContentLoaded() const
|
||||||
@ -1051,20 +965,15 @@ int Task::getAttachmentCount()
|
|||||||
return mAttachmentCount;
|
return mAttachmentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setAttachmentCount(int count)
|
Task& Task::setAttachmentCount(int count)
|
||||||
{
|
{
|
||||||
mAttachmentCount = count;
|
mAttachmentCount = count;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::checkAttachments()
|
int Task::preloadAttachmentCount()
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "select count(*) from file where (taskid = :taskid) and ((removed = 0) or (removed is null))");
|
mAttachmentCount = Storage::instance().findAttachmentCountOnTask(*this);
|
||||||
q.bind(":taskid", (sqlite3_int64)mId);
|
|
||||||
if (q.executeStep())
|
|
||||||
mAttachmentCount = q.getColumn(0).getInt();
|
|
||||||
else
|
|
||||||
mAttachmentCount = 0;
|
|
||||||
|
|
||||||
return mAttachmentCount;
|
return mAttachmentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,9 +982,10 @@ bool Task::isChecked() const
|
|||||||
return mChecked;
|
return mChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setChecked(bool checked)
|
Task& Task::setChecked(bool checked)
|
||||||
{
|
{
|
||||||
mChecked = checked;
|
mChecked = checked;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::getReportedTime() const
|
int Task::getReportedTime() const
|
||||||
@ -1083,9 +993,10 @@ int Task::getReportedTime() const
|
|||||||
return mReportedTime;
|
return mReportedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setReportedTime(int t)
|
Task& Task::setReportedTime(int t)
|
||||||
{
|
{
|
||||||
mReportedTime = t;
|
mReportedTime = t;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::getChildrenReportedTime() const
|
int Task::getChildrenReportedTime() const
|
||||||
@ -1093,9 +1004,10 @@ int Task::getChildrenReportedTime() const
|
|||||||
return mChildrenReportedTime;
|
return mChildrenReportedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setChildrenReportedTime(int t)
|
Task& Task::setChildrenReportedTime(int t)
|
||||||
{
|
{
|
||||||
mChildrenReportedTime = t;
|
mChildrenReportedTime = t;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::flags() const
|
int Task::flags() const
|
||||||
@ -1103,10 +1015,12 @@ int Task::flags() const
|
|||||||
return mFlags;
|
return mFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setFlags(int value)
|
Task& Task::setFlags(int value)
|
||||||
{
|
{
|
||||||
mFlags = value;
|
mFlags = value;
|
||||||
save(Save_Forced);
|
saveAnyway();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::cursorPosition() const
|
int Task::cursorPosition() const
|
||||||
@ -1114,24 +1028,12 @@ int Task::cursorPosition() const
|
|||||||
return mCursorPosition;
|
return mCursorPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::setCursorPosition(int position)
|
Task& Task::setCursorPosition(int position)
|
||||||
{
|
{
|
||||||
mCursorPosition = position;
|
mCursorPosition = position;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
QTextDocument* Task::getTextDocument() const
|
|
||||||
{
|
|
||||||
return mDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::setTextDocument(QTextDocument* doc)
|
|
||||||
{
|
|
||||||
mDocument = doc;
|
|
||||||
if (mDocument)
|
|
||||||
mDocument->setParent(this);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// ----------- Attachment -------------
|
// ----------- Attachment -------------
|
||||||
Attachment::Attachment()
|
Attachment::Attachment()
|
||||||
:mId(0), mTaskId(0)
|
:mId(0), mTaskId(0)
|
||||||
@ -1149,9 +1051,10 @@ Task::Id Attachment::id()
|
|||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::setId(Task::Id id)
|
Attachment& Attachment::setId(Task::Id id)
|
||||||
{
|
{
|
||||||
mId = id;
|
mId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Id Attachment::taskId()
|
Task::Id Attachment::taskId()
|
||||||
@ -1159,9 +1062,10 @@ Task::Id Attachment::taskId()
|
|||||||
return mTaskId;
|
return mTaskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::setTaskId(Task::Id id)
|
Attachment& Attachment::setTaskId(Task::Id id)
|
||||||
{
|
{
|
||||||
mTaskId = id;
|
mTaskId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldId Attachment::worldId() const
|
WorldId Attachment::worldId() const
|
||||||
@ -1169,9 +1073,10 @@ WorldId Attachment::worldId() const
|
|||||||
return mWorldId;
|
return mWorldId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::setWorldId(const WorldId& id)
|
Attachment& Attachment::setWorldId(const WorldId& id)
|
||||||
{
|
{
|
||||||
mWorldId = id;
|
mWorldId = id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Attachment::index()
|
int Attachment::index()
|
||||||
@ -1179,34 +1084,28 @@ int Attachment::index()
|
|||||||
return mIndex;
|
return mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::setIndex(int index)
|
Attachment& Attachment::setIndex(int index)
|
||||||
{
|
{
|
||||||
//TODO: introduce mIndexModified field and corresponding login in save()
|
//TODO: introduce mIndexModified field and corresponding login in save()
|
||||||
mIndex = index;
|
mIndex = index;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Attachment::loadContent()
|
QByteArray Attachment::loadContent()
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "select content from file where id = :id");
|
return Storage::instance().loadContent(*this);
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
|
||||||
if (q.executeStep())
|
|
||||||
return QByteArray((const char*)q.getColumn(0).getBlob(), q.getColumn(0).size());
|
|
||||||
else
|
|
||||||
return QByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::saveContent(const QByteArray& content)
|
Attachment& Attachment::saveContent(const QByteArray& content)
|
||||||
{
|
{
|
||||||
SQLite::Statement q(Storage::instance().database(), "update file set content = :content where id = :id");
|
Storage::instance().saveContent(*this, content);
|
||||||
q.bind(":content", content.data(), content.size());
|
return *this;
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
|
||||||
if (q.exec())
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::setFilename(const QString& filename)
|
Attachment& Attachment::setFilename(const QString& filename)
|
||||||
{
|
{
|
||||||
mFilename = filename;
|
mFilename = filename;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Attachment::filename()
|
QString Attachment::filename()
|
||||||
@ -1214,33 +1113,16 @@ QString Attachment::filename()
|
|||||||
return mFilename;
|
return mFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mDatabase->exec("CREATE TABLE file (id INTEGER PRIMARY KEY, removed INTEGER, taskid INTEGER, filename TEXT, content BLOB, orderid INTEGER, synctime TEXT)");
|
Attachment& Attachment::saveMetadata()
|
||||||
|
|
||||||
void Attachment::save()
|
|
||||||
{
|
{
|
||||||
if (mId)
|
auto id = Storage::instance().saveMetadata(*this);
|
||||||
{
|
if (id != 0)
|
||||||
SQLite::Statement q(Storage::instance().database(), "update file set filename = :filename, orderid = :orderid where id = :id");
|
mId = id;
|
||||||
q.bind(":filename", mFilename.toStdString().c_str());
|
|
||||||
q.bind(":orderid", mIndex);
|
|
||||||
q.bind(":id", (sqlite3_int64)mId);
|
|
||||||
|
|
||||||
if (q.exec())
|
return *this;
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SQLite::Statement q(Storage::instance().database(), "insert into file (filename, taskid, orderid, removed) values(:filename, :taskid, :orderid, 0)");
|
|
||||||
q.bind(":filename", mFilename.toStdString().c_str());
|
|
||||||
q.bind(":taskid", (sqlite3_int64)mTaskId);
|
|
||||||
q.bind(":orderid", mIndex);
|
|
||||||
if (q.exec())
|
|
||||||
{
|
|
||||||
mId = Storage::instance().database().getLastInsertRowid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attachment::load()
|
Attachment& Attachment::loadMetadata()
|
||||||
{
|
{
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,16 +40,21 @@ public:
|
|||||||
~TimeRecord();
|
~TimeRecord();
|
||||||
|
|
||||||
time_t startTime() const;
|
time_t startTime() const;
|
||||||
void setStartTime(const time_t& startTime);
|
TimeRecord& setStartTime(const time_t& startTime);
|
||||||
|
|
||||||
time_t endTime() const;
|
time_t endTime() const;
|
||||||
void setEndTime(const time_t& endTime);
|
TimeRecord& setEndTime(const time_t& endTime);
|
||||||
|
|
||||||
int length();
|
int length();
|
||||||
|
|
||||||
Id id() const;
|
Id id() const;
|
||||||
void setId(Id id);
|
TimeRecord& setId(Id id);
|
||||||
|
|
||||||
Id taskId() const;
|
Id taskId() const;
|
||||||
void setTaskId(Id id);
|
TimeRecord& setTaskId(Id id);
|
||||||
|
|
||||||
WorldId worldId() const;
|
WorldId worldId() const;
|
||||||
void setWorldId(const WorldId& id);
|
TimeRecord& setWorldId(const WorldId& id);
|
||||||
|
|
||||||
// Save record to DB. If record is new - id() property will be set after this call.
|
// Save record to DB. If record is new - id() property will be set after this call.
|
||||||
void save();
|
void save();
|
||||||
@ -74,6 +79,7 @@ typedef std::map<int, QSharedPointer<MonthesMap> > YearsMap;
|
|||||||
|
|
||||||
class TimeLine
|
class TimeLine
|
||||||
{
|
{
|
||||||
|
friend class Storage;
|
||||||
public:
|
public:
|
||||||
TimeLine();
|
TimeLine();
|
||||||
~TimeLine();
|
~TimeLine();
|
||||||
@ -91,7 +97,7 @@ public:
|
|||||||
void save();
|
void save();
|
||||||
|
|
||||||
Id taskId();
|
Id taskId();
|
||||||
void setTaskId(Id id);
|
TimeLine& setTaskId(Id id);
|
||||||
|
|
||||||
// These methods work with local time
|
// These methods work with local time
|
||||||
// Returns set of available years in timeline
|
// Returns set of available years in timeline
|
||||||
@ -168,6 +174,8 @@ class Task: public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
friend class Storage;
|
||||||
|
|
||||||
typedef uint64_t Id;
|
typedef uint64_t Id;
|
||||||
typedef uint32_t ModelId;
|
typedef uint32_t ModelId;
|
||||||
enum Flag
|
enum Flag
|
||||||
@ -181,37 +189,32 @@ public:
|
|||||||
void load(SQLite::Statement& q);
|
void load(SQLite::Statement& q);
|
||||||
|
|
||||||
Id id() const;
|
Id id() const;
|
||||||
void setId(Id id);
|
Task& setId(Id id);
|
||||||
|
|
||||||
Id parentId() const;
|
Id parentId() const;
|
||||||
void setParentId(Id id);
|
Task& setParentId(Id id);
|
||||||
|
|
||||||
WorldId worldId() const;
|
WorldId worldId() const;
|
||||||
void setWorldId(const WorldId& id);
|
Task& setWorldId(const WorldId& id);
|
||||||
|
|
||||||
ModelId modelId() const;
|
ModelId modelId() const;
|
||||||
void setModelId(ModelId id);
|
Task& setModelId(ModelId id);
|
||||||
|
|
||||||
int index() const;
|
int index() const;
|
||||||
void setIndex(int index, bool modified = true);
|
Task& setIndex(int index, bool modified = true);
|
||||||
|
|
||||||
enum SaveOptions
|
void save();
|
||||||
{
|
void saveAnyway();
|
||||||
Save_Automatic,
|
|
||||||
Save_Forced
|
|
||||||
};
|
|
||||||
|
|
||||||
void save(SaveOptions options = Save_Automatic);
|
|
||||||
|
|
||||||
QString html() const;
|
QString html() const;
|
||||||
void setHtml(const QString& html);
|
Task& setHtml(const QString& html);
|
||||||
QString title() const;
|
QString title() const;
|
||||||
void setTitle(const QString& title, bool modified = true);
|
Task& setTitle(const QString& title, bool modified = true);
|
||||||
|
|
||||||
QString path() const;
|
QString path() const;
|
||||||
|
|
||||||
PTask parent() const;
|
PTask parent() const;
|
||||||
void setParent(PTask task, bool modified = true);
|
Task& setParent(PTask task, bool modified = true);
|
||||||
|
|
||||||
TaskArray& children();
|
TaskArray& children();
|
||||||
|
|
||||||
@ -226,24 +229,24 @@ public:
|
|||||||
|
|
||||||
// Returns true if task has attachments
|
// Returns true if task has attachments
|
||||||
int getAttachmentCount();
|
int getAttachmentCount();
|
||||||
void setAttachmentCount(int count);
|
Task& setAttachmentCount(int count);
|
||||||
int checkAttachments();
|
int preloadAttachmentCount();
|
||||||
|
|
||||||
// Service properties used in time reporting
|
// Service properties used in time reporting
|
||||||
bool isChecked() const;
|
bool isChecked() const;
|
||||||
void setChecked(bool checked);
|
Task& setChecked(bool checked);
|
||||||
|
|
||||||
int getReportedTime() const;
|
int getReportedTime() const;
|
||||||
void setReportedTime(int t);
|
Task& setReportedTime(int t);
|
||||||
|
|
||||||
int getChildrenReportedTime() const;
|
int getChildrenReportedTime() const;
|
||||||
void setChildrenReportedTime(int t);
|
Task& setChildrenReportedTime(int t);
|
||||||
|
|
||||||
int flags() const;
|
int flags() const;
|
||||||
void setFlags(int value);
|
Task& setFlags(int value);
|
||||||
|
|
||||||
int cursorPosition() const;
|
int cursorPosition() const;
|
||||||
void setCursorPosition(int position);
|
Task& setCursorPosition(int position);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
QUndoStack* getUndoStack() const;
|
QUndoStack* getUndoStack() const;
|
||||||
@ -270,30 +273,31 @@ protected:
|
|||||||
|
|
||||||
class Attachment
|
class Attachment
|
||||||
{
|
{
|
||||||
|
friend class Storage;
|
||||||
public:
|
public:
|
||||||
Attachment();
|
Attachment();
|
||||||
~Attachment();
|
~Attachment();
|
||||||
|
|
||||||
Task::Id id();
|
Task::Id id();
|
||||||
void setId(Task::Id id);
|
Attachment& setId(Task::Id id);
|
||||||
|
|
||||||
Task::Id taskId();
|
Task::Id taskId();
|
||||||
void setTaskId(Task::Id id);
|
Attachment& setTaskId(Task::Id id);
|
||||||
|
|
||||||
WorldId worldId() const;
|
WorldId worldId() const;
|
||||||
void setWorldId(const WorldId& id);
|
Attachment& setWorldId(const WorldId& id);
|
||||||
|
|
||||||
int index();
|
int index();
|
||||||
void setIndex(int index);
|
Attachment& setIndex(int index);
|
||||||
|
|
||||||
QByteArray loadContent();
|
QByteArray loadContent();
|
||||||
void saveContent(const QByteArray& content);
|
Attachment& saveContent(const QByteArray& content);
|
||||||
|
|
||||||
void setFilename(const QString& filename);
|
Attachment& setFilename(const QString& filename);
|
||||||
QString filename();
|
QString filename();
|
||||||
|
|
||||||
void save();
|
Attachment& saveMetadata();
|
||||||
void load();
|
Attachment& loadMetadata();
|
||||||
protected:
|
protected:
|
||||||
Id mId, mTaskId;
|
Id mId, mTaskId;
|
||||||
WorldId mWorldId;
|
WorldId mWorldId;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
TaskAction::TaskAction(PTask task)
|
TaskAction::TaskAction(PTask task)
|
||||||
:mTask(task)
|
:mTask(task)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ TaskAction::~TaskAction()
|
|||||||
|
|
||||||
PTask TaskAction::task() const
|
PTask TaskAction::task() const
|
||||||
{
|
{
|
||||||
return mTask;
|
return mTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ History ------------------
|
// ------------ History ------------------
|
||||||
@ -33,161 +33,158 @@ ChangesHistory::~ChangesHistory()
|
|||||||
|
|
||||||
void ChangesHistory::setTaskTreeModel(TaskTreeModel* model)
|
void ChangesHistory::setTaskTreeModel(TaskTreeModel* model)
|
||||||
{
|
{
|
||||||
mTaskModel = model;
|
mTaskModel = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangesHistory::setAttachmentsModel(AttachmentsListModel* model)
|
void ChangesHistory::setAttachmentsModel(AttachmentsListModel* model)
|
||||||
{
|
{
|
||||||
mAttachmentsModel = model;
|
mAttachmentsModel = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskTreeModel* ChangesHistory::taskTreeModel() const
|
TaskTreeModel* ChangesHistory::taskTreeModel() const
|
||||||
{
|
{
|
||||||
return mTaskModel;
|
return mTaskModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachmentsListModel* ChangesHistory::attachmentsModel() const
|
AttachmentsListModel* ChangesHistory::attachmentsModel() const
|
||||||
{
|
{
|
||||||
return mAttachmentsModel;
|
return mAttachmentsModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangesHistory::add(PTaskAction action)
|
void ChangesHistory::add(PTaskAction action)
|
||||||
{
|
{
|
||||||
// See if there are "undo"ed actions in the list now
|
// See if there are "undo"ed actions in the list now
|
||||||
if (mRollbackCount > 0)
|
if (mRollbackCount > 0)
|
||||||
{
|
{
|
||||||
// Just delete from list - these changes are not in DB already
|
// Just delete from list - these changes are not in DB already
|
||||||
mActionList.erase(mActionList.begin() + mActionList.size() - mRollbackCount, mActionList.end());
|
mActionList.erase(mActionList.begin() + mActionList.size() - mRollbackCount, mActionList.end());
|
||||||
mRollbackCount = 0;
|
mRollbackCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply change
|
// Apply change
|
||||||
if (action->commit(mTaskModel, mAttachmentsModel))
|
if (action->commit(mTaskModel, mAttachmentsModel))
|
||||||
mActionList.push_back(action);
|
mActionList.push_back(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangesHistory::undo()
|
void ChangesHistory::undo()
|
||||||
{
|
{
|
||||||
// If there are actions that can be "undo"
|
// If there are actions that can be "undo"
|
||||||
if (mActionList.size() - mRollbackCount > 0)
|
if (mActionList.size() - mRollbackCount > 0)
|
||||||
{
|
|
||||||
mRollbackCount++;
|
|
||||||
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
|
|
||||||
if (action->rollback(mTaskModel, mAttachmentsModel))
|
|
||||||
{
|
{
|
||||||
|
mRollbackCount++;
|
||||||
|
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
|
||||||
|
if (action->rollback(mTaskModel, mAttachmentsModel))
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangesHistory::redo()
|
void ChangesHistory::redo()
|
||||||
{
|
{
|
||||||
if (mRollbackCount > 0)
|
if (mRollbackCount > 0)
|
||||||
{
|
|
||||||
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
|
|
||||||
mRollbackCount--;
|
|
||||||
if (action->commit(mTaskModel, mAttachmentsModel))
|
|
||||||
{
|
{
|
||||||
|
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
|
||||||
|
mRollbackCount--;
|
||||||
|
if (action->commit(mTaskModel, mAttachmentsModel))
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChangesHistory::canRedo() const
|
bool ChangesHistory::canRedo() const
|
||||||
{
|
{
|
||||||
return mRollbackCount > 0;
|
return mRollbackCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChangesHistory::canUndo() const
|
bool ChangesHistory::canUndo() const
|
||||||
{
|
{
|
||||||
return mRollbackCount < mActionList.size();
|
return mRollbackCount < mActionList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ChangesHistory HistoryStaticInstance;
|
static ChangesHistory HistoryStaticInstance;
|
||||||
ChangesHistory& ChangesHistory::instance()
|
ChangesHistory& ChangesHistory::instance()
|
||||||
{
|
{
|
||||||
return HistoryStaticInstance;
|
return HistoryStaticInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ ImportAttachmentAction ----
|
// ------------ ImportAttachmentAction ----
|
||||||
#define ImportAttachmentId int(1)
|
#define ImportAttachmentId int(1)
|
||||||
|
|
||||||
ImportAttachmentAction::ImportAttachmentAction(PTask task, const QString &path, int index)
|
ImportAttachmentAction::ImportAttachmentAction(PTask task, const QString &path, int index)
|
||||||
:TaskAction(task), mPath(path), mIndex(index)
|
:TaskAction(task), mPath(path), mIndex(index)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ImportAttachmentAction::~ImportAttachmentAction()
|
ImportAttachmentAction::~ImportAttachmentAction()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool ImportAttachmentAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool ImportAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
QFile f(mPath);
|
QFile f(mPath);
|
||||||
f.open(QFile::ReadOnly);
|
f.open(QFile::ReadOnly);
|
||||||
if (!f.isOpen())
|
if (!f.isOpen())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Get data from file
|
// Get data from file
|
||||||
QByteArray content = f.readAll();
|
QByteArray content = f.readAll();
|
||||||
|
|
||||||
// Compress them
|
// Compress them
|
||||||
QByteArray compressed = qCompress(content);
|
QByteArray compressed = qCompress(content);
|
||||||
|
|
||||||
// Put it to Attachment instance
|
// Put it to Attachment instance
|
||||||
mAttachment = PAttachment(new Attachment());
|
QFileInfo fi(mPath);
|
||||||
mAttachment->setTaskId(mTask->id());
|
mAttachment = PAttachment(new Attachment());
|
||||||
mAttachment->setIndex(mIndex);
|
mAttachment->setTaskId(mTask->id())
|
||||||
|
.setIndex(mIndex)
|
||||||
|
.setFilename(fi.fileName())
|
||||||
|
.saveMetadata()
|
||||||
|
.saveContent(compressed);
|
||||||
|
|
||||||
QFileInfo fi(mPath);
|
return true;
|
||||||
mAttachment->setFilename(fi.fileName());
|
|
||||||
|
|
||||||
// Save everything
|
|
||||||
mAttachment->save();
|
|
||||||
mAttachment->saveContent(compressed);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImportAttachmentAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool ImportAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
Storage::instance().deleteAttachment(mAttachment);
|
Storage::instance().deleteAttachment(mAttachment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PAttachment ImportAttachmentAction::attachment() const
|
PAttachment ImportAttachmentAction::attachment() const
|
||||||
{
|
{
|
||||||
return mAttachment;
|
return mAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ RenameAttachmentAction ---
|
// ------------ RenameAttachmentAction ---
|
||||||
#define RenameAttachmentId int(2)
|
#define RenameAttachmentId int(2)
|
||||||
|
|
||||||
RenameAttachmentAction::RenameAttachmentAction(PTask task, PAttachment attachment, const QString &newname)
|
RenameAttachmentAction::RenameAttachmentAction(PTask task, PAttachment attachment, const QString &newname)
|
||||||
:TaskAction(task), mAttachment(attachment), mNewName(newname)
|
:TaskAction(task), mAttachment(attachment), mNewName(newname)
|
||||||
{
|
{
|
||||||
mName = mAttachment->filename();
|
mName = mAttachment->filename();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenameAttachmentAction::~RenameAttachmentAction()
|
RenameAttachmentAction::~RenameAttachmentAction()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenameAttachmentAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool RenameAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
|
||||||
{
|
{
|
||||||
mAttachment->setFilename(mNewName);
|
mAttachment->setFilename(mNewName)
|
||||||
mAttachment->save();
|
.saveMetadata();
|
||||||
|
|
||||||
if (attModel)
|
if (attModel)
|
||||||
{
|
{
|
||||||
int row = attModel->findRow(mAttachment);
|
int row = attModel->findRow(mAttachment);
|
||||||
QModelIndex index = attModel->index(row, 0);
|
QModelIndex index = attModel->index(row, 0);
|
||||||
attModel->dataChanged(index, index);
|
attModel->dataChanged(index, index);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenameAttachmentAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool RenameAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
mAttachment->setFilename(mName);
|
mAttachment->setFilename(mName)
|
||||||
mAttachment->save();
|
.saveMetadata();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ DeleteAttachmentAction ---
|
// ------------ DeleteAttachmentAction ---
|
||||||
@ -195,70 +192,68 @@ bool RenameAttachmentAction::rollback(TaskTreeModel* taskModel, AttachmentsListM
|
|||||||
#define DeleteAttachmentId int(3)
|
#define DeleteAttachmentId int(3)
|
||||||
|
|
||||||
DeleteAttachmentAction::DeleteAttachmentAction(PTask task, QModelIndexList& mil)
|
DeleteAttachmentAction::DeleteAttachmentAction(PTask task, QModelIndexList& mil)
|
||||||
:TaskAction(task), mIndexList(mil)
|
:TaskAction(task), mIndexList(mil)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DeleteAttachmentAction::~DeleteAttachmentAction()
|
DeleteAttachmentAction::~DeleteAttachmentAction()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool DeleteAttachmentAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool DeleteAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
|
||||||
{
|
{
|
||||||
if (!attModel)
|
if (!attModel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mAttachments.clear();
|
mAttachments.clear();
|
||||||
|
|
||||||
foreach (const QModelIndex& index, mIndexList)
|
foreach (const QModelIndex& index, mIndexList)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PAttachment att = attModel->itemAt(index.row());
|
PAttachment att = attModel->itemAt(index.row());
|
||||||
|
|
||||||
// Remove from DB
|
// Remove from DB
|
||||||
Storage::instance().deleteAttachment(att);
|
Storage::instance().deleteAttachment(att);
|
||||||
|
|
||||||
// Remove from model
|
// Remove from model
|
||||||
attModel->removeItem(index.row());
|
attModel->removeItem(index.row());
|
||||||
|
|
||||||
mAttachments.push_back(att);
|
mAttachments.push_back(att);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate other items and decrease their DB table's orderid field
|
// Iterate other items and decrease their DB table's orderid field
|
||||||
for (int row = 0; row < attModel->rowCount(); row++)
|
for (int row = 0; row < attModel->rowCount(); row++)
|
||||||
{
|
{
|
||||||
Attachment& att = *attModel->itemAt(row);
|
Attachment& att = *attModel->itemAt(row);
|
||||||
att.setIndex(row);
|
att.setIndex(row)
|
||||||
att.save();
|
.saveMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeleteAttachmentAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel)
|
bool DeleteAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
|
||||||
{
|
{
|
||||||
while (!mAttachments.isEmpty())
|
while (!mAttachments.isEmpty())
|
||||||
{
|
{
|
||||||
auto iter = std::min_element(mAttachments.begin(), mAttachments.end(), [] (const PAttachment& a, const PAttachment& b) { return a->index() < b->index();});
|
auto iter = std::min_element(mAttachments.begin(), mAttachments.end(), [] (const PAttachment& a, const PAttachment& b) { return a->index() < b->index();});
|
||||||
PAttachment attToUndelete = *iter;
|
PAttachment attToUndelete = *iter;
|
||||||
|
|
||||||
// Restore attachment in database
|
// Restore attachment in database
|
||||||
Storage::instance().undeleteAttachment(attToUndelete);
|
Storage::instance().undeleteAttachment(attToUndelete);
|
||||||
|
|
||||||
attModel->addItem(attToUndelete);
|
attModel->addItem(attToUndelete);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return true;
|
||||||
|
|
||||||
//Storage::instance().undeleteAttachment(mAttachment);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ NewTaskAction ------------
|
// ------------ NewTaskAction ------------
|
||||||
#define NewTaskId int(4)
|
#define NewTaskId int(4)
|
||||||
|
|
||||||
NewTaskAction::NewTaskAction(PTask parent, int index, const QString &title)
|
NewTaskAction::NewTaskAction(PTask parent, int index, const QString &title)
|
||||||
:TaskAction(PTask()), mParent(parent), mIndex(index), mTitle(title)
|
:TaskAction(PTask()), mParent(parent), mIndex(index), mTitle(title)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
NewTaskAction::~NewTaskAction()
|
NewTaskAction::~NewTaskAction()
|
||||||
@ -266,50 +261,50 @@ NewTaskAction::~NewTaskAction()
|
|||||||
|
|
||||||
bool NewTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool NewTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mParent);
|
QModelIndex parentIndex = taskModel->getIndex(mParent);
|
||||||
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
||||||
//taskModel->rowCount(parentIndex), taskModel->rowCount(parentIndex));
|
//taskModel->rowCount(parentIndex), taskModel->rowCount(parentIndex));
|
||||||
}
|
}
|
||||||
if (!mTask)
|
if (!mTask)
|
||||||
{
|
{
|
||||||
mTask = Storage::instance().createTask(mParent, mIndex);
|
mTask = Storage::instance().createTask(mParent, mIndex);
|
||||||
mTask->setTitle(mTitle);
|
mTask->setTitle(mTitle);
|
||||||
mTask->save();
|
mTask->save();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Storage::instance().undeleteTask(mTask);
|
Storage::instance().undeleteTask(mTask);
|
||||||
|
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NewTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool NewTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
// Get parent index
|
// Get parent index
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
int row = Storage::instance().findTaskIndexInParent(mTask);
|
int row = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
taskModel->beginRemoveRows(parentIndex, row, row);
|
taskModel->beginRemoveRows(parentIndex, row, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
|
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ RenameTaskAction ---------
|
// ------------ RenameTaskAction ---------
|
||||||
RenameTaskAction::RenameTaskAction(PTask task, const QString &newTitle)
|
RenameTaskAction::RenameTaskAction(PTask task, const QString &newTitle)
|
||||||
:TaskAction(task), mNewTitle(newTitle)
|
:TaskAction(task), mNewTitle(newTitle)
|
||||||
{
|
{
|
||||||
mTitle = mTask->title();
|
mTitle = mTask->title();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenameTaskAction::~RenameTaskAction()
|
RenameTaskAction::~RenameTaskAction()
|
||||||
@ -319,38 +314,38 @@ RenameTaskAction::~RenameTaskAction()
|
|||||||
|
|
||||||
bool RenameTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool RenameTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
mTask->setTitle(mNewTitle);
|
mTask->setTitle(mNewTitle);
|
||||||
mTask->save();
|
mTask->save();
|
||||||
|
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex index = taskModel->getIndex(mTask);
|
QModelIndex index = taskModel->getIndex(mTask);
|
||||||
if (index.isValid())
|
if (index.isValid())
|
||||||
taskModel->dataChanged(index ,index);
|
taskModel->dataChanged(index ,index);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenameTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool RenameTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
mTask->setTitle(mTitle);
|
mTask->setTitle(mTitle);
|
||||||
mTask->save();
|
mTask->save();
|
||||||
|
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex index = taskModel->getIndex(mTask);
|
QModelIndex index = taskModel->getIndex(mTask);
|
||||||
if (index.isValid())
|
if (index.isValid())
|
||||||
taskModel->dataChanged(index, index);
|
taskModel->dataChanged(index, index);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ MoveTaskAction ------------
|
// ------------ MoveTaskAction ------------
|
||||||
MoveTaskAction::MoveTaskAction(PTask task, PTask newParent, int newIndex)
|
MoveTaskAction::MoveTaskAction(PTask task, PTask newParent, int newIndex)
|
||||||
:TaskAction(task), mNewIndex(newIndex), mNewParent(newParent)
|
:TaskAction(task), mNewIndex(newIndex), mNewParent(newParent)
|
||||||
{
|
{
|
||||||
mIndex = mTask->index();
|
mIndex = mTask->index();
|
||||||
mParent = mTask->parent();
|
mParent = mTask->parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveTaskAction::~MoveTaskAction()
|
MoveTaskAction::~MoveTaskAction()
|
||||||
@ -359,75 +354,75 @@ MoveTaskAction::~MoveTaskAction()
|
|||||||
|
|
||||||
bool MoveTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool MoveTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
taskModel->layoutAboutToBeChanged();
|
taskModel->layoutAboutToBeChanged();
|
||||||
|
|
||||||
// Detach it from old parent (if exists)
|
// Detach it from old parent (if exists)
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
int row = Storage::instance().findTaskIndexInParent(mTask);
|
int row = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
taskModel->beginRemoveRows(parentIndex, row, row);
|
taskModel->beginRemoveRows(parentIndex, row, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove task from memory structures only
|
// Remove task from memory structures only
|
||||||
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
|
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
|
||||||
|
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
|
|
||||||
// Move task
|
// Move task
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
|
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
|
||||||
taskModel->beginInsertRows(parentIndex, mNewIndex, mNewIndex);
|
taskModel->beginInsertRows(parentIndex, mNewIndex, mNewIndex);
|
||||||
}
|
}
|
||||||
Storage::instance().moveTask(mTask, mNewParent, mNewIndex);
|
Storage::instance().moveTask(mTask, mNewParent, mNewIndex);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
|
|
||||||
taskModel->layoutChanged();
|
taskModel->layoutChanged();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoveTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool MoveTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
|
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
|
||||||
|
|
||||||
// Tell about removing of row
|
// Tell about removing of row
|
||||||
taskModel->beginRemoveRows(parentIndex, mNewIndex, mNewIndex);
|
taskModel->beginRemoveRows(parentIndex, mNewIndex, mNewIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete from parent
|
// Delete from parent
|
||||||
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
|
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
|
|
||||||
// Reload task if needed
|
// Reload task if needed
|
||||||
mTask->loadContent();
|
mTask->loadContent();
|
||||||
|
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mParent);
|
QModelIndex parentIndex = taskModel->getIndex(mParent);
|
||||||
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move task back
|
// Move task back
|
||||||
Storage::instance().moveTask(mTask, mParent, mIndex);
|
Storage::instance().moveTask(mTask, mParent, mIndex);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------- IncreaseLevelAction -----------
|
// ------- IncreaseLevelAction -----------
|
||||||
IncreaseLevelAction::IncreaseLevelAction(PTask task)
|
IncreaseLevelAction::IncreaseLevelAction(PTask task)
|
||||||
:TaskAction(task)
|
:TaskAction(task)
|
||||||
{
|
{
|
||||||
mOldParent = task->parent();
|
mOldParent = task->parent();
|
||||||
mOldIndex = task->index();
|
mOldIndex = task->index();
|
||||||
}
|
}
|
||||||
|
|
||||||
IncreaseLevelAction::~IncreaseLevelAction()
|
IncreaseLevelAction::~IncreaseLevelAction()
|
||||||
@ -435,9 +430,9 @@ IncreaseLevelAction::~IncreaseLevelAction()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncreaseLevelAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool IncreaseLevelAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
/* if (taskModel)
|
/* if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
int row = Storage::instance().findTaskIndexInParent(mTask);
|
int row = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
@ -448,12 +443,12 @@ bool IncreaseLevelAction::commit(TaskTreeModel* taskModel, AttachmentsListModel*
|
|||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncreaseLevelAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool IncreaseLevelAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
@ -463,12 +458,12 @@ bool IncreaseLevelAction::rollback(TaskTreeModel* taskModel, AttachmentsListMode
|
|||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------- DecreaseLevelAction -----------
|
// ------- DecreaseLevelAction -----------
|
||||||
DecreaseLevelAction::DecreaseLevelAction(PTask task)
|
DecreaseLevelAction::DecreaseLevelAction(PTask task)
|
||||||
:TaskAction(task)
|
:TaskAction(task)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -478,9 +473,9 @@ DecreaseLevelAction::~DecreaseLevelAction()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecreaseLevelAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool DecreaseLevelAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
/* if (taskModel)
|
/* if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
int row = Storage::instance().findTaskIndexInParent(mTask);
|
int row = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
@ -491,12 +486,12 @@ bool DecreaseLevelAction::commit(TaskTreeModel* taskModel, AttachmentsListModel*
|
|||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecreaseLevelAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool DecreaseLevelAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
@ -506,14 +501,14 @@ bool DecreaseLevelAction::rollback(TaskTreeModel* taskModel, AttachmentsListMode
|
|||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------- DeleteTaskAction ---------------
|
// ------- DeleteTaskAction ---------------
|
||||||
DeleteTaskAction::DeleteTaskAction(PTask task)
|
DeleteTaskAction::DeleteTaskAction(PTask task)
|
||||||
:TaskAction(task)
|
:TaskAction(task)
|
||||||
{
|
{
|
||||||
mIndex = Storage::instance().findTaskIndexInParent(mTask);
|
mIndex = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteTaskAction::~DeleteTaskAction()
|
DeleteTaskAction::~DeleteTaskAction()
|
||||||
@ -522,31 +517,52 @@ DeleteTaskAction::~DeleteTaskAction()
|
|||||||
|
|
||||||
bool DeleteTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool DeleteTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
int row = Storage::instance().findTaskIndexInParent(mTask);
|
int row = Storage::instance().findTaskIndexInParent(mTask);
|
||||||
taskModel->beginRemoveRows(parentIndex, row, row);
|
taskModel->beginRemoveRows(parentIndex, row, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
|
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endRemoveRows();
|
taskModel->endRemoveRows();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeleteTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
bool DeleteTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
|
||||||
{
|
{
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
|
||||||
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
|
||||||
}
|
}
|
||||||
Storage::instance().undeleteTask(mTask);
|
Storage::instance().undeleteTask(mTask);
|
||||||
if (taskModel)
|
if (taskModel)
|
||||||
taskModel->endInsertRows();
|
taskModel->endInsertRows();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------- SaveTaskAction --------------
|
||||||
|
SaveTaskAction::SaveTaskAction(const PTask& task)
|
||||||
|
:TaskAction(task)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SaveTaskAction::~SaveTaskAction()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool SaveTaskAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
|
{
|
||||||
|
if (mTask)
|
||||||
|
mTask->save();
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SaveTaskAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#ifndef TASKACTION_H
|
#ifndef TASKACTION_H
|
||||||
#define TASKACTION_H
|
#define TASKACTION_H
|
||||||
|
|
||||||
#include <task.h>
|
#include "task.h"
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QModelIndexList>
|
#include <QModelIndexList>
|
||||||
@ -9,12 +9,15 @@
|
|||||||
class TaskTreeModel;
|
class TaskTreeModel;
|
||||||
class AttachmentsListModel;
|
class AttachmentsListModel;
|
||||||
|
|
||||||
|
// Base class for all actions
|
||||||
class TaskAction
|
class TaskAction
|
||||||
{
|
{
|
||||||
friend class ChangesHistory;
|
friend class ChangesHistory;
|
||||||
public:
|
public:
|
||||||
TaskAction(PTask task);
|
TaskAction(PTask task);
|
||||||
virtual ~TaskAction();
|
virtual ~TaskAction();
|
||||||
|
|
||||||
|
// Associated task
|
||||||
PTask task() const;
|
PTask task() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -45,10 +48,10 @@ public:
|
|||||||
|
|
||||||
static ChangesHistory& instance();
|
static ChangesHistory& instance();
|
||||||
protected:
|
protected:
|
||||||
TaskTreeModel* mTaskModel;
|
TaskTreeModel* mTaskModel = nullptr;
|
||||||
AttachmentsListModel* mAttachmentsModel;
|
AttachmentsListModel* mAttachmentsModel = nullptr;
|
||||||
QVector<PTaskAction> mActionList;
|
QVector<PTaskAction> mActionList;
|
||||||
int mRollbackCount;
|
int mRollbackCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAKE_ACTION(X) ChangesHistory::instance().add(PTaskAction(X))
|
#define MAKE_ACTION(X) ChangesHistory::instance().add(PTaskAction(X))
|
||||||
@ -181,4 +184,15 @@ protected:
|
|||||||
bool rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel);
|
bool rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SaveTaskAction: public TaskAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SaveTaskAction(const PTask& task);
|
||||||
|
~SaveTaskAction() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool commit(TaskTreeModel* taskModel, AttachmentsListModel* attModel);
|
||||||
|
bool rollback(TaskTreeModel* taskModel, AttachmentsListModel* attModel);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // TASKACTION_H
|
#endif // TASKACTION_H
|
||||||
|
|||||||
@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
TaskTreeView::TaskTreeView(QWidget *widget)
|
TaskTreeView::TaskTreeView(QWidget *widget)
|
||||||
:QTreeView(widget)
|
:QTreeView(widget)
|
||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TaskTreeView::dragMoveEvent(QDragMoveEvent* event)
|
void TaskTreeView::dragMoveEvent(QDragMoveEvent* event)
|
||||||
{
|
{
|
||||||
@ -270,15 +268,17 @@ QVariant TaskTreeModel::headerData(int /*section*/, Qt::Orientation /*orientatio
|
|||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
/*if (orientation != Qt::Horizontal)
|
/*
|
||||||
return QVariant();
|
if (orientation != Qt::Horizontal)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return QString(tr("Tasks"));
|
return QString(tr("Tasks"));
|
||||||
}
|
}
|
||||||
return QVariant();*/
|
return QVariant();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::DropActions TaskTreeModel::supportedDropActions() const
|
Qt::DropActions TaskTreeModel::supportedDropActions() const
|
||||||
@ -419,7 +419,8 @@ bool TaskTreeModel::dropMimeData(const QMimeData *mimeData, Qt::DropAction actio
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
|
bool TaskTreeModel::canDropMimeData(const QMimeData */*data*/, Qt::DropAction /*action*/,
|
||||||
|
int /*row*/, int /*column*/, const QModelIndex &/*parent*/) const
|
||||||
{
|
{
|
||||||
//qDebug() << "TaskTreeModel::canDropMimeData() called";
|
//qDebug() << "TaskTreeModel::canDropMimeData() called";
|
||||||
return true;
|
return true;
|
||||||
@ -432,7 +433,7 @@ bool TaskTreeModel::removeRows(int row, int count, const QModelIndex &parent)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Called during drag and drop
|
// Called during drag and drop
|
||||||
if (parent.isValid())
|
/* if (parent.isValid())
|
||||||
{
|
{
|
||||||
PTask parentTask = getTask(parent);
|
PTask parentTask = getTask(parent);
|
||||||
for (int i=0; i<count; i++)
|
for (int i=0; i<count; i++)
|
||||||
@ -461,6 +462,7 @@ bool TaskTreeModel::removeRows(int row, int count, const QModelIndex &parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskTreeModel::insertRows(int /*row*/, int /*count*/, const QModelIndex& /*parent*/)
|
bool TaskTreeModel::insertRows(int /*row*/, int /*count*/, const QModelIndex& /*parent*/)
|
||||||
|
|||||||
@ -396,6 +396,7 @@ void TimeTreeModel::cutInterval(const QModelIndex& index)
|
|||||||
|
|
||||||
beginRemoveRows(index.parent(), index.row(), index.row());
|
beginRemoveRows(index.parent(), index.row(), index.row());
|
||||||
mTimeLine->cutInterval(t);
|
mTimeLine->cutInterval(t);
|
||||||
|
mTimeLine->save();
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user