# # # patch "src/model/Inventory.cpp" # from [f6295d690ed7e9bface0c929f457ab71242b75ba] # to [c76f068669214a19c97df858405a735099390a9f] # # patch "src/model/Inventory.h" # from [a710182d3bbcf99d9992dcc710a6c67d0d14148b] # to [c13128083107dde46436ed0ad304b20de6576f52] # ============================================================ --- src/model/Inventory.cpp f6295d690ed7e9bface0c929f457ab71242b75ba +++ src/model/Inventory.cpp c76f068669214a19c97df858405a735099390a9f @@ -23,9 +23,11 @@ #include "BasicIOParser.h" #include +#include Inventory::Inventory(QObject * parent) - : QAbstractItemModel(parent), AutomateCommand(0), workspacePath() + : QAbstractItemModel(parent), AutomateCommand(0), + workspacePath(), modelWasCreated(false) { rootItem = new PseudoItem("__root", PseudoItem::Root); @@ -33,6 +35,16 @@ Inventory::Inventory(QObject * parent) this, SIGNAL(modelCreated()), this, SLOT(setWorkspacePath()) ); + + connect( + this, SIGNAL(rowsInserted(const QModelIndex & , int , int )), + this, SLOT(noteRowsInserted(const QModelIndex & , int , int )) + ); + + connect( + this, SIGNAL(rowsRemoved(const QModelIndex & , int , int )), + this, SLOT(noteRowsRemoved(const QModelIndex & , int , int )) + ); } Inventory::~Inventory() @@ -55,7 +67,11 @@ void Inventory::readInventory(const QStr cmd << path; } - MonotoneTask task(cmd); + // FIXME: bump to 1 in order to be able to determine + // if a node has subnodes + QStringList opts = QStringList() << "depth" << QString::number(0); + + MonotoneTask task(cmd, opts); AutomateCommand::enqueueWorkspaceTask(workspacePath, task); } @@ -80,32 +96,70 @@ void Inventory::processTaskResult(const I(parser.parse()); StanzaList stanzas = parser.getStanzas(); - QList items; - foreach (Stanza st, stanzas) { InventoryItem * item = new InventoryItem(st); - items.push_back(item); - } + if (item->isDirectory()) + { + PseudoItem * cdUp = new PseudoItem("..", PseudoItem::CdUp); + item->appendChild(cdUp); + } - flatItemList.clear(); - flatItemList = items; + QString path = item->getPath(); + if (itemMap.contains(path)) + { + InventoryItem * oldItem = itemMap.value(path); + L(QString("querying parent index of %1").arg(path)); + QModelIndex parentIndex = indexFromItem(oldItem->parent(), 0); + int row = oldItem->row(); + removeRowsRecursive(parentIndex, row, row); + } - rootItem->deleteAllChildren(); - rootItem->setChildren(buildTreeRecursive(items, NULL)); + ModelItem * parentItem; + if (path.isEmpty()) + { + parentItem = rootItem; + } + else + { + QString baseDir = item->getBaseDirectory(); + // FIXME: this will probably make problems with restricted renames + I(itemMap.contains(baseDir)); + parentItem = itemMap.value(baseDir); + } - // invalidate model indexes and request a repaint - reset(); + QModelIndex parentIndex = indexFromItem(parentItem, 0); + int newRowNumber = parentItem->childCount(); - emit modelCreated(); + beginInsertRows(parentIndex, newRowNumber, newRowNumber); + itemMap.insert(path, item); + parentItem->appendChild(item); + endInsertRows(); + } + + if (!modelWasCreated) + { + modelWasCreated = true; + reset(); + emit modelCreated(); + } } +QModelIndex Inventory::indexFromItem(const ModelItem * item, int col) const +{ + QModelIndex parent; + if (item->parent() != item) + { + indexFromItem(item->parent(), col); + } + return index(item->row(), col, parent); +} + void Inventory::setWorkspacePath() { QList children = rootItem->getChildren(); - // the first item is the cdup pseudo item - I(children.size() > 1); + I(children.size() > 0); QString displayPath = workspacePath; QString homePath = QDir::homePath(); @@ -114,67 +168,11 @@ void Inventory::setWorkspacePath() displayPath = QDir(homePath).relativeFilePath(workspacePath); displayPath.prepend("~/"); } - children[1]->setLabel(displayPath); + children[0]->setLabel(displayPath); - dataChanged(index(0, 0, QModelIndex()), index(0, 2, QModelIndex())); + emit dataChanged(index(0, 0, QModelIndex()), index(0, 2, QModelIndex())); } -QList Inventory::buildTreeRecursive(QList & items, ModelItem * parentItem) -{ - QList finalItems; - - QString parentPath = ""; - - InventoryItem * parent = dynamic_cast(parentItem); - if (parent) - { - parentPath = parent->getPath(); - } - - ModelItem * cdUp = new PseudoItem("..", PseudoItem::CdUp); - cdUp->setParent(parentItem); - finalItems.append(cdUp); - - InventoryItem * currentItem; - - while (items.size() > 0) - { - currentItem = items.front(); - - // - // if the item is not directly inside the current path stop immediately - // - QString tmpPath = parentPath; - tmpPath.append("/"); - tmpPath.append(currentItem->getFilename()); - - // path may not be empty for this condition - if (!parentPath.isEmpty() && currentItem->getPath().compare(tmpPath) != 0) - { - break; - } - - // remove the item if we can append it now - items.pop_front(); - - // - // it seems to be a valid item - // - - // if the item is a directory, catch items inside it - if (currentItem->isDirectory()) - { - currentItem->setChildren(buildTreeRecursive(items, currentItem)); - } - - // append item to final list - finalItems.push_back(currentItem); - - } - - return finalItems; -} - QModelIndex Inventory::index(int row, int column, const QModelIndex & parent) const { ModelItem * parentItem; @@ -302,7 +300,7 @@ QMap Inventory QList missingItems; QList unknownItems; - foreach (InventoryItem * item, flatItemList) + foreach (InventoryItem * item, itemMap.values()) { if (item->hasStatus(InventoryItem::Missing)) { @@ -406,3 +404,46 @@ QMap Inventory return unaccountedRenames; } +void Inventory::removeRowsRecursive(const QModelIndex & parent, int start, int end) +{ + I(parent.isValid()); + + for (int row = start; row <= end; row++) + { + QModelIndex child = index(row, 0, parent); + I(child.isValid()); + + // delete children recursively + int count = rowCount(child); + if (count > 0) + { + removeRowsRecursive(child, 0, count - 1); + } + + beginRemoveRows(parent, row, row); + ModelItem * item = static_cast(child.internalPointer()); + InventoryItem * invitem = qobject_cast(item); + + if (invitem) + itemMap.remove(invitem->getPath()); + + item->parent()->removeChild(item); + delete item; + endRemoveRows(); + } +} + +void Inventory::noteRowsInserted(const QModelIndex & parent, int start, int end) +{ + if (!parent.isValid()) return; + ModelItem * item = static_cast(parent.internalPointer()); + L(QString("Item %1, rows %2 to %3 inserted").arg(item->getLabel()).arg(start).arg(end)); +} + +void Inventory::noteRowsRemoved(const QModelIndex & parent, int start, int end) +{ + if (!parent.isValid()) return; + ModelItem * item = static_cast(parent.internalPointer()); + L(QString("Item %1, rows %2 to %3 removed").arg(item->getLabel()).arg(start).arg(end)); +} + ============================================================ --- src/model/Inventory.h a710182d3bbcf99d9992dcc710a6c67d0d14148b +++ src/model/Inventory.h c13128083107dde46436ed0ad304b20de6576f52 @@ -35,7 +35,6 @@ public: QMap findUnaccountedRenames(); - // needed Qt Model methods QVariant data(const QModelIndex &, int) const; Qt::ItemFlags flags(const QModelIndex &) const; QVariant headerData(int, Qt::Orientation, int) const; @@ -50,15 +49,19 @@ private: private: void processTaskResult(const MonotoneTask &); - QList buildTreeRecursive(QList &, ModelItem *); + QModelIndex indexFromItem(const ModelItem *, int) const; + void removeRowsRecursive(const QModelIndex &, int, int); - ModelItem * rootItem; - QString branchName; - QList flatItemList; - WorkspacePath workspacePath; + ModelItem * rootItem; + QString branchName; + QMap itemMap; + WorkspacePath workspacePath; + bool modelWasCreated; private slots: void setWorkspacePath(); + void noteRowsInserted( const QModelIndex & , int , int ); + void noteRowsRemoved( const QModelIndex & , int , int ); signals: void modelCreated();