# # # patch "src/model/Inventory.cpp" # from [306e575d9882570219c9011fafa57427bbde165b] # to [4affff131bf9b3bbf87b6d2c38112754af3dfba9] # # patch "src/model/Inventory.h" # from [a66c6d72381d4628a70ab35445a8eedbfa6e0a99] # to [c9663f40bd61cac606d5f3015c76fd78e8914fa6] # # patch "src/model/InventoryItem.cpp" # from [24fa3cfb08bc571383fd8917f6b9c0670c15854f] # to [8655d1aa49754ba6086412b51272c7ae348c3d7e] # # patch "src/model/InventoryItem.h" # from [d12b8e0ac122d45e23670a363b67e509f860372f] # to [f54099a6b7833ec7559ea50cca52b7a5ecdd8bed] # # patch "src/model/InventoryModel.cpp" # from [449f8bff08ed3c9316cc5d59ccb6eac1fe71d19e] # to [028ac6e66b46adf8c754ce35f4ad01be36019c70] # # patch "src/model/InventoryModel.h" # from [79749c6f114e8202469c52b73014322d28083834] # to [c4bdceaabf117ed45fe64da4bd3d56ca6d9e31a1] # # patch "src/model/InventoryWatcher.cpp" # from [eb4db8f6cd3d776a5c4ff210ede88dad0058e13b] # to [06eba8a6db3e127b2e8c32cc20e02e64953d8249] # # patch "src/model/InventoryWatcher.h" # from [08010c5c36ef15d3d2107a749de8f293f2961a8b] # to [f5d337e80e158b61ebf075791c1725dabd7c460b] # # patch "src/view/InventoryView.cpp" # from [bbc8682e8ac362ff0b909a7162f4a47589ec34e4] # to [4dc2768b6d4dacd9c81420ded69f83fe689ee464] # # patch "src/view/InventoryView.h" # from [c3bbc745b0e5b49a883a888ce8efef698640a9aa] # to [4600fd50ceb332bde69a80bf6284e727732035f9] # ============================================================ --- src/model/Inventory.cpp 306e575d9882570219c9011fafa57427bbde165b +++ src/model/Inventory.cpp 4affff131bf9b3bbf87b6d2c38112754af3dfba9 @@ -118,6 +118,9 @@ void Inventory::processTaskResult(const if (QFile::exists(workspacePath + "/" + itemMap[queriedPath]->getPath())) { D(QString("keeping existing unknown node %1").arg(queriedPath)); + // clear the previous state of the node and its children + itemMap[queriedPath]->setStatusRecursive(InventoryItem::Unknown); + emit dataChanged(itemMap[queriedPath]); return; } ============================================================ --- src/model/Inventory.h a66c6d72381d4628a70ab35445a8eedbfa6e0a99 +++ src/model/Inventory.h c9663f40bd61cac606d5f3015c76fd78e8914fa6 @@ -57,6 +57,8 @@ signals: void beginRemoveRows(ModelItem *, int, int); void endRemoveRows(); + void dataChanged(ModelItem *); + void inventoryRead(const QString &); void invalidWorkspaceFormat(const QString &); }; ============================================================ --- src/model/InventoryItem.cpp 24fa3cfb08bc571383fd8917f6b9c0670c15854f +++ src/model/InventoryItem.cpp 8655d1aa49754ba6086412b51272c7ae348c3d7e @@ -358,6 +358,23 @@ bool InventoryItem::hasNotStatus(int sta return (status & statusBits) == 0; } +void InventoryItem::setStatusRecursive(int statusBits) +{ + status = statusBits; + if (!isDirectory()) + { + return; + } + + for (int i=0,s=children.size(); i(children.at(i)); + // skip everything other than InventoryItems + if (!item) continue; + item->setStatusRecursive(statusBits); + } +} + int InventoryItem::getStatusRecursive() const { int overallStatus = status; @@ -508,7 +525,7 @@ bool InventoryItem::isExpanded(int level if (childCount() == 0) { - W(QString("node %1 has no children").arg(getPath())); + D(QString("node %1 has no children").arg(getPath())); return false; } ============================================================ --- src/model/InventoryItem.h d12b8e0ac122d45e23670a363b67e509f860372f +++ src/model/InventoryItem.h f54099a6b7833ec7559ea50cca52b7a5ecdd8bed @@ -115,6 +115,7 @@ public: void setAboutToBeExpanded(); bool isAboutToBeExpanded() const; + void setStatusRecursive(int); int getStatusRecursive() const; bool hasChangedRecursive() const; ============================================================ --- src/model/InventoryModel.cpp 449f8bff08ed3c9316cc5d59ccb6eac1fe71d19e +++ src/model/InventoryModel.cpp 028ac6e66b46adf8c754ce35f4ad01be36019c70 @@ -52,6 +52,11 @@ InventoryModel::InventoryModel(QObject * inventory, SIGNAL(endRemoveRows()), this, SLOT(triggerEndRemoveRows()) ); + + connect( + inventory, SIGNAL(dataChanged(ModelItem *)), + this, SLOT(triggerDataChanged(ModelItem *)) + ); } InventoryModel::~InventoryModel() @@ -347,3 +352,8 @@ void InventoryModel::triggerEndRemoveRow endRemoveRows(); } +void InventoryModel::triggerDataChanged(ModelItem * item) +{ + emit dataChanged(indexFromItem(item, 0), indexFromItem(item, 2)); +} + ============================================================ --- src/model/InventoryModel.h 79749c6f114e8202469c52b73014322d28083834 +++ src/model/InventoryModel.h c4bdceaabf117ed45fe64da4bd3d56ca6d9e31a1 @@ -68,6 +68,8 @@ private slots: void triggerBeginRemoveRows(ModelItem *, int, int); void triggerEndRemoveRows(); + void triggerDataChanged(ModelItem *); + void maybeResetModel(const QString &); signals: ============================================================ --- src/model/InventoryWatcher.cpp eb4db8f6cd3d776a5c4ff210ede88dad0058e13b +++ src/model/InventoryWatcher.cpp 06eba8a6db3e127b2e8c32cc20e02e64953d8249 @@ -18,6 +18,7 @@ #include "InventoryWatcher.h" #include "InventoryItem.h" +#include "BasicIOParser.h" InventoryWatcher::InventoryWatcher(QObject * parent) : QFileSystemWatcher(parent) @@ -35,9 +36,26 @@ InventoryWatcher::~InventoryWatcher() {} InventoryWatcher::~InventoryWatcher() {} +//! TODO: monitor _MTN/options for changes as well void InventoryWatcher::setWorkspacePath(const WorkspacePath & wp) { workspace = wp; + QString revPath(workspace + "/_MTN/revision"); + QFile file(revPath); + if (!file.open(QIODevice::ReadOnly)) + { + F(QString("cannot open %1/_MTN/revision for reading").arg(workspace)); + } + QString contents(file.readAll()); + file.close(); + + BasicIOParser parser(contents); + if (!parser.parse()) + { + F("could not parse contents of _MTN/revision"); + } + oldRevisionEntries = parser.getStanzas(); + addPath(revPath); } void InventoryWatcher::watchPaths(const QStringList & paths) @@ -69,7 +87,164 @@ void InventoryWatcher::pathChanged(const void InventoryWatcher::pathChanged(const QString & path) { I(path.indexOf(workspace) != -1); + + if (path == QString(workspace + "/_MTN/revision")) + { + checkForBookkeepChanges(); + // we need to re-add this path since + // mtn apparently re-creates the file + addPath(workspace + "/_MTN/revision"); + return; + } + QString pathComponent = path.mid(path.indexOf(workspace) + workspace.length() + 1); emit changedPath(pathComponent); } +void InventoryWatcher::checkForBookkeepChanges() +{ + QFile file(workspace + "/_MTN/revision"); + if (!file.open(QIODevice::ReadOnly)) + { + F(QString("cannot open %1/_MTN/revision for reading").arg(workspace)); + } + QString contents(file.readAll()); + file.close(); + + BasicIOParser parser(contents); + if (!parser.parse()) + { + F("could not parse contents of _MTN/revision"); + } + StanzaList newRevisionEntries = parser.getStanzas(); + + QStringList notifiedPaths; + + foreach (Stanza newStanza, newRevisionEntries) + { + QString newEntryType = newStanza.at(0).sym; + // we don't care about patches, since we're notified of them + // separately; and the other two are uninteresting for us as well + if (newEntryType == "format_version" || + newEntryType == "new_manifest" || + newEntryType == "patch") + { + continue; + } + + bool foundOrAlreadyHandled = false; + + for (int i=0; i