QModelIndex ListModel::_appendAfter(ListItem* item, const QString& content, App::AppendMode mode) { SqlQuery sql; ListItem* parent = item->parent(); if (!parent) return QModelIndex(); // cannot append after the root int row = mode == App::AppendAfter ? item->row() + 1 : item->row(); sql.prepare("UPDATE list_item SET weight = weight + 1 WHERE list_id = :list AND parent_id = :parent AND weight >= :weight"); sql.bindValue(":list", _listId); sql.bindValue(":parent", parent->id()); sql.bindValue(":weight", row); if (!sql.exec()) return QModelIndex(); sql.prepare("INSERT INTO list_item (list_id, parent_id, weight, content, created_at) VALUES (:list, :parent, :weight, :content, CURRENT_TIMESTAMP)"); sql.bindValue(":list", _listId); sql.bindValue(":parent", parent->id()); sql.bindValue(":weight", row); sql.bindValue(":content", content); if (!sql.exec()) return QModelIndex(); int id = sql.lastInsertId().toInt(); beginInsertRows(indexFromItem(parent), row, row); ListItem* newItem = new ListItem(_listId, id, content); parent->insertChild(row, newItem); if (isNewItemCheckable(item->parent(), row)) newItem->setCheckable(true); endInsertRows(); return indexFromItem(newItem); }
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; } } }
QModelIndex ListModel::appendChild(const QModelIndex& parent, int row, QString content) { if (parent.isValid() && parent.column() != 0) return QModelIndex(); ListItem* parentItem = itemFromIndex(parent); if (!parentItem) return QModelIndex(); SqlQuery sql; sql.prepare("UPDATE list_item SET weight = weight + 1 WHERE parent_id = :parent AND weight >= :row"); sql.bindValue(":list", _listId); sql.bindValue(":parent", parentItem->id()); sql.bindValue(":row", row); if (!sql.exec()) return QModelIndex(); sql.prepare("INSERT INTO list_item (list_id, parent_id, weight, content, created_at) VALUES (:list, :parent, :row, :content, CURRENT_TIMESTAMP)"); sql.bindValue(":list", _listId); sql.bindValue(":parent", parentItem->id()); sql.bindValue(":row", row); sql.bindValue(":content", content); if (!sql.exec()) return QModelIndex(); int id = sql.lastInsertId().toInt(); beginInsertRows(parent, row, row); ListItem* newItem = new ListItem(_listId, id, content); if (isNewItemCheckable(parentItem, row)) newItem->setCheckable(true); parentItem->insertChild(row, newItem); endInsertRows(); return indexFromItem(newItem); }