noo/client/taskaction.cpp

569 lines
14 KiB
C++

#include "taskaction.h"
#include "storage.h"
#include "tasktreemodel.h"
#include "attachmentslist.h"
#include <QFile>
#include <QFileInfo>
#include <QByteArray>
TaskAction::TaskAction(PTask task)
:mTask(task)
{
}
TaskAction::~TaskAction()
{
}
PTask TaskAction::task() const
{
return mTask;
}
// ------------ History ------------------
ChangesHistory::ChangesHistory()
{
}
ChangesHistory::~ChangesHistory()
{
}
void ChangesHistory::setTaskTreeModel(TaskTreeModel* model)
{
mTaskModel = model;
}
void ChangesHistory::setAttachmentsModel(AttachmentsListModel* model)
{
mAttachmentsModel = model;
}
TaskTreeModel* ChangesHistory::taskTreeModel() const
{
return mTaskModel;
}
AttachmentsListModel* ChangesHistory::attachmentsModel() const
{
return mAttachmentsModel;
}
void ChangesHistory::add(PTaskAction action)
{
// See if there are "undo"ed actions in the list now
if (mRollbackCount > 0)
{
// Just delete from list - these changes are not in DB already
mActionList.erase(mActionList.begin() + mActionList.size() - mRollbackCount, mActionList.end());
mRollbackCount = 0;
}
// Apply change
if (action->commit(mTaskModel, mAttachmentsModel))
mActionList.push_back(action);
}
void ChangesHistory::undo()
{
// If there are actions that can be "undo"
if (mActionList.size() - mRollbackCount > 0)
{
mRollbackCount++;
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
if (action->rollback(mTaskModel, mAttachmentsModel))
{
}
}
}
void ChangesHistory::redo()
{
if (mRollbackCount > 0)
{
PTaskAction& action = mActionList[mActionList.size() - mRollbackCount];
mRollbackCount--;
if (action->commit(mTaskModel, mAttachmentsModel))
{
}
}
}
bool ChangesHistory::canRedo() const
{
return mRollbackCount > 0;
}
bool ChangesHistory::canUndo() const
{
return mRollbackCount < mActionList.size();
}
static ChangesHistory HistoryStaticInstance;
ChangesHistory& ChangesHistory::instance()
{
return HistoryStaticInstance;
}
// ------------ ImportAttachmentAction ----
#define ImportAttachmentId int(1)
ImportAttachmentAction::ImportAttachmentAction(PTask task, const QString &path, int index)
:TaskAction(task), mPath(path), mIndex(index)
{}
ImportAttachmentAction::~ImportAttachmentAction()
{}
bool ImportAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
QFile f(mPath);
f.open(QFile::ReadOnly);
if (!f.isOpen())
return false;
// Get data from file
QByteArray content = f.readAll();
// Compress them
QByteArray compressed = qCompress(content);
// Put it to Attachment instance
QFileInfo fi(mPath);
mAttachment = PAttachment(new Attachment());
mAttachment->setTaskId(mTask->id())
.setIndex(mIndex)
.setFilename(fi.fileName())
.saveMetadata()
.saveContent(compressed);
return true;
}
bool ImportAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
Storage::instance().deleteAttachment(mAttachment);
return true;
}
PAttachment ImportAttachmentAction::attachment() const
{
return mAttachment;
}
// ------------ RenameAttachmentAction ---
#define RenameAttachmentId int(2)
RenameAttachmentAction::RenameAttachmentAction(PTask task, PAttachment attachment, const QString &newname)
:TaskAction(task), mAttachment(attachment), mNewName(newname)
{
mName = mAttachment->filename();
}
RenameAttachmentAction::~RenameAttachmentAction()
{
}
bool RenameAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
{
mAttachment->setFilename(mNewName)
.saveMetadata();
if (attModel)
{
int row = attModel->findRow(mAttachment);
QModelIndex index = attModel->index(row, 0);
attModel->dataChanged(index, index);
}
return true;
}
bool RenameAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
mAttachment->setFilename(mName)
.saveMetadata();
return true;
}
// ------------ DeleteAttachmentAction ---
#define DeleteAttachmentId int(3)
DeleteAttachmentAction::DeleteAttachmentAction(PTask task, QModelIndexList& mil)
:TaskAction(task), mIndexList(mil)
{}
DeleteAttachmentAction::~DeleteAttachmentAction()
{}
bool DeleteAttachmentAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
{
if (!attModel)
return false;
mAttachments.clear();
foreach (const QModelIndex& index, mIndexList)
{
if (!index.isValid())
continue;
PAttachment att = attModel->itemAt(index.row());
// Remove from DB
Storage::instance().deleteAttachment(att);
// Remove from model
attModel->removeItem(index.row());
mAttachments.push_back(att);
}
// Iterate other items and decrease their DB table's orderid field
for (int row = 0; row < attModel->rowCount(); row++)
{
Attachment& att = *attModel->itemAt(row);
att.setIndex(row)
.saveMetadata();
}
return true;
}
bool DeleteAttachmentAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* attModel)
{
while (!mAttachments.isEmpty())
{
auto iter = std::min_element(mAttachments.begin(), mAttachments.end(), [] (const PAttachment& a, const PAttachment& b) { return a->index() < b->index();});
PAttachment attToUndelete = *iter;
// Restore attachment in database
Storage::instance().undeleteAttachment(attToUndelete);
attModel->addItem(attToUndelete);
}
return true;
}
// ------------ NewTaskAction ------------
#define NewTaskId int(4)
NewTaskAction::NewTaskAction(PTask parent, int index, const QString &title)
:TaskAction(PTask()), mParent(parent), mIndex(index), mTitle(title)
{}
NewTaskAction::~NewTaskAction()
{}
bool NewTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mParent);
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
//taskModel->rowCount(parentIndex), taskModel->rowCount(parentIndex));
}
if (!mTask)
{
mTask = Storage::instance().createTask(mParent, mIndex);
mTask->setTitle(mTitle);
mTask->save();
}
else
Storage::instance().undeleteTask(mTask);
if (taskModel)
taskModel->endInsertRows();
return true;
}
bool NewTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
if (taskModel)
{
// Get parent index
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
int row = Storage::instance().findTaskIndexInParent(mTask);
taskModel->beginRemoveRows(parentIndex, row, row);
}
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
if (taskModel)
{
taskModel->endRemoveRows();
}
return true;
}
// ------------ RenameTaskAction ---------
RenameTaskAction::RenameTaskAction(PTask task, const QString &newTitle)
:TaskAction(task), mNewTitle(newTitle)
{
mTitle = mTask->title();
}
RenameTaskAction::~RenameTaskAction()
{
}
bool RenameTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
mTask->setTitle(mNewTitle);
mTask->save();
if (taskModel)
{
QModelIndex index = taskModel->getIndex(mTask);
if (index.isValid())
taskModel->dataChanged(index ,index);
}
return true;
}
bool RenameTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
mTask->setTitle(mTitle);
mTask->save();
if (taskModel)
{
QModelIndex index = taskModel->getIndex(mTask);
if (index.isValid())
taskModel->dataChanged(index, index);
}
return true;
}
// ------------ MoveTaskAction ------------
MoveTaskAction::MoveTaskAction(PTask task, PTask newParent, int newIndex)
:TaskAction(task), mNewIndex(newIndex), mNewParent(newParent)
{
mIndex = mTask->index();
mParent = mTask->parent();
}
MoveTaskAction::~MoveTaskAction()
{
}
bool MoveTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
taskModel->layoutAboutToBeChanged();
// Detach it from old parent (if exists)
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
int row = Storage::instance().findTaskIndexInParent(mTask);
taskModel->beginRemoveRows(parentIndex, row, row);
}
// Remove task from memory structures only
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
if (taskModel)
taskModel->endRemoveRows();
// Move task
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
taskModel->beginInsertRows(parentIndex, mNewIndex, mNewIndex);
}
Storage::instance().moveTask(mTask, mNewParent, mNewIndex);
if (taskModel)
taskModel->endInsertRows();
taskModel->layoutChanged();
return true;
}
bool MoveTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mNewParent);
// Tell about removing of row
taskModel->beginRemoveRows(parentIndex, mNewIndex, mNewIndex);
}
// Delete from parent
Storage::instance().deleteTask(mTask, Storage::DeleteOption_FromParent);
if (taskModel)
taskModel->endRemoveRows();
// Reload task if needed
mTask->loadContent();
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mParent);
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
}
// Move task back
Storage::instance().moveTask(mTask, mParent, mIndex);
if (taskModel)
taskModel->endInsertRows();
return true;
}
// ------- IncreaseLevelAction -----------
IncreaseLevelAction::IncreaseLevelAction(PTask task)
:TaskAction(task)
{
mOldParent = task->parent();
mOldIndex = task->index();
}
IncreaseLevelAction::~IncreaseLevelAction()
{
}
bool IncreaseLevelAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
/* if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
int row = Storage::instance().findTaskIndexInParent(mTask);
taskModel->beginRemoveRows(parentIndex, row, row);
}
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
if (taskModel)
taskModel->endRemoveRows();
*/
return true;
}
bool IncreaseLevelAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
/*
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
}
Storage::instance().undeleteTask(mTask);
if (taskModel)
taskModel->endInsertRows();
*/
return true;
}
// ------- DecreaseLevelAction -----------
DecreaseLevelAction::DecreaseLevelAction(PTask task)
:TaskAction(task)
{
}
DecreaseLevelAction::~DecreaseLevelAction()
{
}
bool DecreaseLevelAction::commit(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
/* if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
int row = Storage::instance().findTaskIndexInParent(mTask);
taskModel->beginRemoveRows(parentIndex, row, row);
}
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
if (taskModel)
taskModel->endRemoveRows();
*/
return true;
}
bool DecreaseLevelAction::rollback(TaskTreeModel* /*taskModel*/, AttachmentsListModel* /*attModel*/)
{
/*
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
}
Storage::instance().undeleteTask(mTask);
if (taskModel)
taskModel->endInsertRows();
*/
return true;
}
// ------- DeleteTaskAction ---------------
DeleteTaskAction::DeleteTaskAction(PTask task)
:TaskAction(task)
{
mIndex = Storage::instance().findTaskIndexInParent(mTask);
}
DeleteTaskAction::~DeleteTaskAction()
{
}
bool DeleteTaskAction::commit(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
int row = Storage::instance().findTaskIndexInParent(mTask);
taskModel->beginRemoveRows(parentIndex, row, row);
}
Storage::instance().deleteTask(mTask, Storage::DeleteOption_Total);
if (taskModel)
taskModel->endRemoveRows();
return true;
}
bool DeleteTaskAction::rollback(TaskTreeModel* taskModel, AttachmentsListModel* /*attModel*/)
{
if (taskModel)
{
QModelIndex parentIndex = taskModel->getIndex(mTask->parent());
taskModel->beginInsertRows(parentIndex, mIndex, mIndex);
}
Storage::instance().undeleteTask(mTask);
if (taskModel)
taskModel->endInsertRows();
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;
}