X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=src%2Ftaskmodel.cpp;fp=src%2Ftaskmodel.cpp;h=b76baf3e1f74163dce0b0e328e1735a4d53b1de6;hb=d483bd8e6523c23c6f1d8908a2e0611c2bc9ff4f;hp=0000000000000000000000000000000000000000;hpb=7dfa3fe589d1722d49681f42cdb0bf1e6efb5223;p=sven%2Fvym.git diff --git a/src/taskmodel.cpp b/src/taskmodel.cpp new file mode 100644 index 0000000..b76baf3 --- /dev/null +++ b/src/taskmodel.cpp @@ -0,0 +1,529 @@ +#include "taskmodel.h" + +#include + +#include "branchitem.h" +#include "branchobj.h" +#include "task.h" +#include "vymmodel.h" + +TaskModel::TaskModel(QObject *parent) : QAbstractTableModel(parent) +{ + showParentsLevel = 0; + + QSize size = QSize(22, 22); + QSize size2 = QSize(44, 22); + + arrow_up_icon = + QIcon(QPixmap(":/flag-arrow-up.svg").scaled(size, Qt::KeepAspectRatio)); + arrow_2up_icon = QIcon( + QPixmap(":/flag-arrow-2up.svg").scaled(size, Qt::KeepAspectRatio)); + + task_new_icon = + QIcon(QPixmap(":/flag-task-new.svg").scaled(size, Qt::KeepAspectRatio)); + task_new_morning_icon = QIcon(QPixmap(":/flag-task-new-morning.svg") + .scaled(size, Qt::KeepAspectRatio)); + task_new_sleeping_icon = QIcon(QPixmap(":/flag-task-new-sleeping.svg") + .scaled(size, Qt::KeepAspectRatio)); + + task_wip_icon = + QIcon(QPixmap(":/flag-task-wip.svg").scaled(size, Qt::KeepAspectRatio)); + task_wip_morning_icon = QIcon(QPixmap(":/flag-task-wip-morning.svg") + .scaled(size, Qt::KeepAspectRatio)); + task_wip_sleeping_icon = QIcon(QPixmap(":/flag-task-wip-sleeping.svg") + .scaled(size, Qt::KeepAspectRatio)); + + task_finished_icon = QIcon( + QPixmap(":/flag-task-finished.svg").scaled(size, Qt::KeepAspectRatio)); + + taskfilter_stopsign_icon = + QIcon(QPixmap(":/flag-stopsign.svg").scaled(size, Qt::KeepAspectRatio)); + taskfilter_stopsign_arrow_up_icon = + QIcon(QPixmap(":/flag-stopsign-arrow-up.png") + .scaled(size2, Qt::KeepAspectRatio)); + taskfilter_stopsign_arrow_2up_icon = + QIcon(QPixmap(":/flag-stopsign-arrow-2up.png") + .scaled(size2, Qt::KeepAspectRatio)); +} + +QModelIndex TaskModel::index(Task *t) const +{ + int n = tasks.indexOf(t); + if (n < 0) + return QModelIndex(); + else + return createIndex(n, 0, t); +} + +QModelIndex TaskModel::indexRowEnd(Task *t) +{ + int n = tasks.indexOf(t); + if (n < 0) + return QModelIndex(); + else + return createIndex(n, 8, t); +} + +Task *TaskModel::getTask(const QModelIndex &ix) const +{ + if (ix.isValid()) + return tasks.at(ix.row()); + else + return NULL; +} + +Task *TaskModel::getTask(const int i) const +{ + if (i >= 0 && i < count()) + return getTask(createIndex(i, 0)); + else + return NULL; +} + +int TaskModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return tasks.size(); +} + +int TaskModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 9; +} + +QVariant TaskModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= tasks.size() || index.row() < 0) + return QVariant(); + + BranchItem *bi = tasks.at(index.row())->getBranch(); + Task *t = tasks.at(index.row()); + + if (role == Qt::DisplayRole) { + if (index.column() == 0) + return t->getPriority(); + else if (index.column() == 1) + return t->getPriorityDelta(); + else if (index.column() == 2) + return QString(); // return t->getStatusString() + " - " + // +t->getAwakeString(); + else if (index.column() == 3) + return t->getAgeCreation(); + else if (index.column() == 4) + return t->getAgeModification(); + else if (index.column() == 5) { + if (t->getDaysSleep() > 0) + return t->getDaysSleep(); + else + return "-"; + } + else if (index.column() == 6) { + QString s = bi->getModel()->getMapName(); + if (s.isEmpty()) + return "-"; + else + return bi->getModel()->getMapName(); + } + else if (index.column() == 8) { + BranchItem *bi = tasks.at(index.row())->getBranch(); + return bi->getHeadingPlainWithParents(showParentsLevel); + } + } + else if (role == Qt::DecorationRole && index.column() == 2) { + QString s = t->getIconString(); + if (s == "task-new") + return task_new_icon; + else if (s == "task-new-morning") + return task_new_morning_icon; + else if (s == "task-new-sleeping") + return task_new_sleeping_icon; + else if (s == "task-wip") + return task_wip_icon; + else if (s == "task-wip-sleeping") + return task_wip_sleeping_icon; + else if (s == "task-wip-morning") + return task_wip_morning_icon; + else if (s == "task-finished") + return task_finished_icon; + else { + qWarning() << "Unknown task type in TaskModel::data: " << s; + return QVariant(); + } + } + else if (role == Qt::DecorationRole && index.column() == 7) { + BranchItem *bi = t->getBranch(); + if (bi->hasActiveFlag("stopsign")) { + if (bi->hasActiveFlag("2arrow-up")) + return taskfilter_stopsign_arrow_2up_icon; + else if (bi->hasActiveFlag("arrow-up")) + return taskfilter_stopsign_arrow_up_icon; + else + return taskfilter_stopsign_icon; + } + else { + if (bi->hasActiveFlag("2arrow-up")) + return arrow_2up_icon; + else if (bi->hasActiveFlag("arrow-up")) + return arrow_up_icon; + } + return QIcon(); + } + else // role != Qt::DisplayRole + { + if (role == Qt::EditRole && index.column() == 1) // DeltaPrio + return t->getPriorityDelta(); + if (role == Qt::ForegroundRole && bi) + return bi->getHeadingColor(); + if (role == Qt::BackgroundRole && bi) { + BranchItem *frameBI = bi->getFramedParentBranch(bi); + if (frameBI && index.column() != 5) { + BranchObj *bo = frameBI->getBranchObj(); + if (bo) + // Return frame background + return bo->getFrameBrushColor(); + } + else { + // Return map background + return bi->getModel()->getMapBackgroundColor(); + } + } + } + + return QVariant(); +} + +QVariant TaskModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) { + switch (section) { + case 0: + return tr("Prio", "TaskEditor"); + case 1: + return tr("Delta", "TaskEditor"); + case 2: + return tr("Status", "TaskEditor"); + case 3: + return tr("Age total", "TaskEditor"); + case 4: + return tr("Age mod.", "TaskEditor"); + case 5: + return tr("Sleep", "TaskEditor"); + case 6: + return tr("Map", "TaskEditor"); + case 7: + return tr("Flags", "TaskEditor"); + case 8: + return tr("Task", "TaskEditor"); + default: + return QVariant(); + } + } + return QVariant(); +} + +bool TaskModel::insertRows(int position, int rows, const QModelIndex &index, + Task *t) +{ + Q_UNUSED(index); + beginInsertRows(QModelIndex(), position, position + rows - 1); + + for (int row = 0; row < rows; row++) + tasks.insert(position, t); + + endInsertRows(); + return true; +} + +bool TaskModel::removeRows(int position, int rows, const QModelIndex &index) +{ + Q_UNUSED(index); + beginRemoveRows(QModelIndex(), position, position + rows - 1); + + for (int row = 0; row < rows; ++row) + delete (tasks.takeAt(position)); + + endRemoveRows(); + return true; +} + +bool TaskModel::setData(const QModelIndex &index, const QVariant &value, + int role) +{ + if (index.isValid() && role == Qt::EditRole) { + Task *t = tasks.at(index.row()); + if (!t) { + qWarning() << "TaskModel::setData no task found"; + return false; + } + + if (index.column() == 1) // set Delta Priority + { + BranchItem *bi = t->getBranch(); + VymModel *m = bi->getModel(); + m->setTaskPriorityDelta(value.toInt(), bi); + recalcPriorities(); + emit(dataChanged(index, index)); + return true; + } + if (index.column() == 8) // set Heading + { + BranchItem *bi = t->getBranch(); + VymModel *m = bi->getModel(); + m->setHeadingPlainText(value.toString(), bi); + emit(dataChanged(index, index)); + return true; + } + } + + return false; +} + +void TaskModel::emitDataChanged(Task *t) +{ + QModelIndex ix = index(t); + if (ix.isValid()) { + int row = ix.row(); + int col = 0; + while (col < columnCount(QModelIndex())) { + ix = createIndex(row, col, t); + if (ix.isValid()) + emit(dataChanged(ix, ix)); + col++; + } + } +} + +Qt::ItemFlags TaskModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled; + + return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | + Qt::ItemIsDropEnabled | Qt::ItemIsEditable; +} + +int TaskModel::count(VymModel *model) const +{ + if (!model) + return tasks.size(); + int n = 0; + foreach (Task *t, tasks) + if (t->getBranch()->getModel() == model) + n++; + return n; +} + +Task *TaskModel::createTask(BranchItem *bi) +{ + if (bi) { + foreach (Task *t, tasks) { + if (t->getBranch() == bi) { + qWarning() << "TaskModel::createTask Branch exists already!"; + return NULL; + } + } + Task *task = new Task(this); + task->setBranch(bi); + task->setAwake(Task::Morning); + insertRows(tasks.count(), 1, QModelIndex(), task); + + bi->setTask(task); + + return task; + } + qWarning() << "TaskEditor::addItem - item exists"; + return NULL; +} + +void TaskModel::deleteTask(Task *t) +{ + int pos = tasks.indexOf(t); + if (pos >= 0) + removeRows(pos, 1, QModelIndex()); +} + +bool TaskModel::updateAwake(bool force) +{ + bool awake_changed = false; + foreach (Task *t, tasks) { + if (t->updateAwake() || force) { + t->getBranch()->updateTaskFlag(); + awake_changed = true; + } + } + return awake_changed; +} + +void TaskModel::recalcPriorities() +{ + emit(layoutAboutToBeChanged()); + int minPrio = 1000000; + foreach (Task *t, tasks) { + int p = 0; + BranchItem *bi = t->getBranch(); + + // Status + switch (t->getStatus()) { + case Task::NotStarted: + break; + case Task::WIP: + p += 10; + break; + case Task::Finished: + p += 2000; + break; + } + + // Awake and sleeping + switch (t->getAwake()) { + case Task::Morning: + p -= 1000; + break; + case Task::WideAwake: + break; + case Task::Sleeping: + //p += 1000 + t->getDaysSleep(); + break; + } + + // Color (importance) + QColor c = bi->getHeadingColor(); + + // light blueish green + if (c == QColor("#00aa7f")) + p -= 20; + + // green (e.g. from vym < 2.6.3 with #005500) + if (c.red() == 0 && c.blue() == 0 && c.green() < 160) + p -= 40; + + // orange + if (c == QColor("#d95100")) + p -= 60; + + // red + if (c == QColor("#ff0000")) + p -= 80; + + // Flags + if (bi->hasActiveFlag("stopsign")) + p -= 450; + if (bi->hasActiveFlag("2arrow-up")) + p -= 1000; + if (bi->hasActiveFlag("arrow-up")) + p -= 500; + + // Age + p -= t->getAgeModification(); + p -= t->getAgeCreation() * 1.0 / 365 * + 80; // After a year, this is as important as "red" + + // Position in subtree + p += bi->num(); + + // Priority delta (set menually) + p -= t->getPriorityDelta(); + + // Set priority finally + t->setPriority(p); + if (p < minPrio) + minPrio = p; + } + // Normalize, so that most important task has prio 1 + foreach (Task *t, tasks) { + t->setPriority(1 - minPrio + t->getPriority()); + } + + emit(layoutChanged()); +} + +void TaskModel::setShowParentsLevel(uint i) +{ + showParentsLevel = i; + recalcPriorities(); // Triggers update of view +} + +uint TaskModel::getShowParentsLevel() { return showParentsLevel; } + +Qt::DropActions TaskModel::supportedDropActions() const +{ + return Qt::MoveAction; +} + +QStringList TaskModel::mimeTypes() const +{ + QStringList types; + types << "application/vnd.text.list"; + return types; +} + +QMimeData *TaskModel::mimeData(const QModelIndexList &indexes) const +{ + QMimeData *mimeData = new QMimeData(); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + + if (indexes.count() > 0 && indexes.first().isValid()) { + Task *task = getTask(indexes.first()); + + // Field 0: Heading + QString text = task->getBranch()->getHeadingPlain(); + stream << text; + + // Field 1: task row + stream << QString::number(index(task).row()); + } + + mimeData->setData("application/vnd.text.list", encodedData); + return mimeData; +} + +bool TaskModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + Q_UNUSED(row); + + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat("application/vnd.text.list")) + return false; + + if (column > 0) + return false; + + QByteArray encodedData = data->data("application/vnd.text.list"); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + QStringList newItems; + int rows = 0; + + while (!stream.atEnd()) { + QString text; + stream >> text; + newItems << text; + ++rows; + } + + Task *dst = getTask(parent); + Task *src = getTask(newItems[1].toInt()); + + // qDebug() << "Dropping: " << src->getBranch()->getHeadingPlain() << " on + // " << dst->getBranch()->getHeadingPlain(); + + int delta_p = dst->getPriority() - src->getPriority(); + + src->setPriorityDelta(src->getPriorityDelta() - delta_p + 1); + BranchItem *bi = src->getBranch(); + bi->getModel()->emitDataChanged(bi); + bi->getModel()->setChanged(); + return true; +}