QModelIndex ListModel::moveItemHorizontal(const QModelIndex& index, int direction) { ListItem* item = itemFromIndex(index); if (!item) return index; ListItem* parent = item->parent(); int row = item->row(); if (direction == App::Left) { // reparent as child of parent's parent if (!parent || parent->isRoot()) // already top level item return index; ListItem* newParent = parent->parent(); int newRow = parent->row() + 1; QSqlDatabase db = QSqlDatabase::database(); db.transaction(); if (parent->takeChildDb(row) && item->setParentDb(newParent, newRow)) { db.commit(); if (beginMoveRows(indexFromItem(parent), row, row, indexFromItem(newParent), newRow)) { newParent->insertChild(newRow, parent->takeChild(row)); endMoveRows(); } return indexFromItem(item); } else { db.rollback(); return index; } } else { // move as child of previous sibling ListItem* newParent = parent->child(row - 1); if (!newParent) return index; QSqlDatabase db = QSqlDatabase::database(); db.transaction(); if (parent->takeChildDb(row) && item->setParentDb(newParent, newParent->childCount())) { db.commit(); if (beginMoveRows(indexFromItem(parent), row, row, indexFromItem(newParent), newParent->childCount())) { newParent->appendChild(parent->takeChild(row)); endMoveRows(); } newParent->setExpanded(true); return indexFromItem(item); } else { db.rollback(); return index; } } }
void ListModel::removeItem(const QModelIndex& index) { if (!index.isValid()) return; ListItem* item = itemFromIndex(index); if (!item) return; bool isProject = item->isProject(); ListItem* parent = item->parent(); // disable removing the last child if (parent == root() && root()->childCount() == 1) return; int row = item->row(); beginRemoveRows(indexFromItem(parent), row, row); QSqlDatabase db = QSqlDatabase::database(); db.transaction(); if (_removeItem(item)) { db.commit(); if (isProject) emit projectRemoved(); } else { db.rollback(); } endRemoveRows(); }
QModelIndex ListModel::moveItemVertical(const QModelIndex& index, App::Direction direction) { ListItem* item = itemFromIndex(index); if (!item) return index; int row = item->row(); if (direction == App::Up && row == 0) return index; ListItem* parent = item->parent(); if (direction == App::Down && row == (parent->childCount() - 1)) return index; ListItem* otherItem = parent->child(direction == App::Up ? row - 1 : row + 1); int downRow = direction == App::Down ? row : row - 1; // the row that is being moved down QSqlDatabase db = QSqlDatabase::database(); db.transaction(); if (item->setRow(direction == App::Down ? row + 1 : row - 1) && otherItem->setRow(row)) { db.commit(); if (beginMoveRows(index.parent(), downRow, downRow, index.parent(), downRow + 2)) { parent->moveChild(downRow); endMoveRows(); return indexFromItem(item); } } else db.rollback(); return index; }
void ListModel::sort(ListItem* parent, App::SortMode mode) { int count = parent->childCount(); QVector<QPair<ListItem*, int>> sorting(count); for (int i = 0; i < count; ++i) { sorting[i].first = parent->child(i); sorting[i].second = i; } if (!parent->sort(mode)) return; QModelIndexList oldIndexes; QModelIndexList newIndexes; for (QModelIndex idx : persistentIndexList()) { ListItem* item = itemFromIndex(idx); if (!item) continue; if (idx.row() != item->row()) { oldIndexes.append(idx); newIndexes.append(indexFromItem(item)); } } qDebug() << __FUNCTION__ << oldIndexes; qDebug() << __FUNCTION__ << newIndexes; changePersistentIndexList(oldIndexes, newIndexes); emit layoutChanged(); }
QModelIndex ListModel::parent(const QModelIndex& index) const { if (!index.isValid()) // root return QModelIndex(); ListItem* item = itemFromIndex(index); if (!item) return QModelIndex(); ListItem* parent = item->parent(); if (parent->isRoot()) // top level item return QModelIndex(); return createIndex(parent->row(), 0, parent); }
QVariant ListModel::data(const QModelIndex& index, int role) const { if (index.isValid()) { ListItem* item = itemFromIndex(index); if (item) { // all columns switch (role) { case Qt::BackgroundRole: if (item->isHighlighted()) return App::HighlightBackgroundColor; else if (item->isProject()) return App::ProjectBackgroundColor; else if (item->isMilestone()) return App::MilestoneBackgroundColor; else return QVariant(); } // specific column switch (index.column()) { case 0: switch (role) { case Qt::DisplayRole: return item->html(); case Qt::EditRole: return item->markdown(); case Qt::CheckStateRole: if (item->isCheckable()) if (item->isCompleted()) return Qt::Checked; else if (item->isCancelled()) return Qt::PartiallyChecked; else return Qt::Unchecked; break; case Qt::DecorationRole: if (item->isProject()) return Util::findIcon("project"); if (item->isMilestone()) return Util::findIcon("milestone"); if (item->isNote()) return Util::findIcon("note"); break; #ifdef QT_DEBUG case Qt::ToolTipRole: return QString("id: %1 row: %2 parent: %3 milestone: %4 priority: %5").arg(item->id()).arg(item->row()).arg(item->parent()->id()).arg(item->isMilestone()).arg(item->priority()); #endif } break; case 1: switch (role) { case Qt::DisplayRole: return item->dueDate(); } break; } } } return QVariant(); }