# # # patch "src/model/InventoryWatcher.cpp" # from [f7bbca911f47fafb1ceeafbd8ae6f02e1b55005e] # to [3317cac3e99937ee0a09a7ca24d7380132cfa969] # # patch "src/model/InventoryWatcher.h" # from [f5d337e80e158b61ebf075791c1725dabd7c460b] # to [38da4783eb30f74bff1e75c2cace46ab150a06f1] # ============================================================ --- src/model/InventoryWatcher.cpp f7bbca911f47fafb1ceeafbd8ae6f02e1b55005e +++ src/model/InventoryWatcher.cpp 3317cac3e99937ee0a09a7ca24d7380132cfa969 @@ -32,6 +32,13 @@ InventoryWatcher::InventoryWatcher(QObje this, SIGNAL(fileChanged(const QString &)), this, SLOT(pathChanged(const QString &)) ); + + notifyTimer = new QTimer(this); + + connect( + notifyTimer, SIGNAL(timeout()), + this, SLOT(notifyChangedPaths()) + ); } InventoryWatcher::~InventoryWatcher() {} @@ -97,10 +104,95 @@ void InventoryWatcher::pathChanged(const return; } - QString pathComponent = path.mid(path.indexOf(workspace) + workspace.length() + 1); - emit changedPath(pathComponent); + addPathAndStartTimer( + path.mid(path.indexOf(workspace) + workspace.length() + 1) + ); } +void InventoryWatcher::addPathAndStartTimer(const QString & newPath) +{ + // + // The following algorithm only picks those paths for an update + // which are not a sub path of an already existing path + // + // current: "a/b" "b/c" + // add "g": "a/b" "b/c" "g" + // add "b": "a/b" "b" + // add "a/b/c": "a/b" "b/c" + // add "": "" + // + QStringList actualNotifiedPaths; + if (newPath.isEmpty()) + { + actualNotifiedPaths.append(""); + } + else + { + enum { skip, replace, add } action; + + action = add; + foreach (QString oldPath, changedPaths) + { + if (newPath.startsWith(oldPath + "/") || + newPath == oldPath || oldPath == "") + { + action = skip; + break; + } + if (oldPath.startsWith(newPath + "/")) + { + action = replace; + } + } + + if (action == add) + { + actualNotifiedPaths = changedPaths; + actualNotifiedPaths.append(newPath); + } + else + if (action == replace) + { + foreach (QString oldPath, changedPaths) + { + if (!oldPath.startsWith(newPath + "/")) + { + actualNotifiedPaths.append(oldPath); + } + } + actualNotifiedPaths.append(newPath); + } + else + if (action == skip) + { + actualNotifiedPaths = changedPaths; + } + else + I(false); + } + + changedPaths = actualNotifiedPaths; + + if (notifyTimer->isActive()) + { + notifyTimer->stop(); + } + + // FIXME: make this configurable eventually + notifyTimer->start(500); +} + +void InventoryWatcher::notifyChangedPaths() +{ + notifyTimer->stop(); + D(QString("notifying changed paths %1").arg(changedPaths.join(","))); + foreach (QString path, changedPaths) + { + emit changedPath(path); + } + changedPaths.clear(); +} + void InventoryWatcher::checkForBookkeepChanges() { QFile file(workspace + "/_MTN/revision"); @@ -118,9 +210,8 @@ void InventoryWatcher::checkForBookkeepC C("could not parse contents of _MTN/revision"); return; } - StanzaList newRevisionEntries = parser.getStanzas(); - QStringList notifiedPaths; + StanzaList newRevisionEntries = parser.getStanzas(); foreach (const Stanza & newStanza, newRevisionEntries) { @@ -209,42 +300,14 @@ void InventoryWatcher::checkForBookkeepC if (foundOrAlreadyHandled) continue; - QString path = newStanza.at(0).vals.at(0); - foreach (const QString & handledPath, notifiedPaths) - { - if (path.indexOf(handledPath + "/") != -1) - { - foundOrAlreadyHandled = true; - break; - } - } - - if (foundOrAlreadyHandled) continue; - - notifiedPaths.push_back(path); - emit changedPath(path); + addPathAndStartTimer(newStanza.at(0).vals.at(0)); } // now loop through all the left old items; // we should only have a subset of items in this list now foreach (const Stanza & oldStanza, oldRevisionEntries) { - QString path = oldStanza.at(0).vals.at(0); - - bool alreadyNotified = false; - foreach (const QString & handledPath, notifiedPaths) - { - if (path.indexOf(handledPath + "/")) - { - alreadyNotified = true; - break; - } - } - - if (alreadyNotified) continue; - - notifiedPaths.push_back(path); - emit changedPath(path); + addPathAndStartTimer(oldStanza.at(0).vals.at(0)); } oldRevisionEntries = newRevisionEntries; ============================================================ --- src/model/InventoryWatcher.h f5d337e80e158b61ebf075791c1725dabd7c460b +++ src/model/InventoryWatcher.h 38da4783eb30f74bff1e75c2cace46ab150a06f1 @@ -22,6 +22,7 @@ #include "vocab.h" #include #include +#include class InventoryWatcher : public QFileSystemWatcher { @@ -40,13 +41,17 @@ private: void unwatchPaths(const QStringList &); private: + void addPathAndStartTimer(const QString &); void checkForBookkeepChanges(); WorkspacePath workspace; StanzaList oldRevisionEntries; + QStringList changedPaths; + QTimer * notifyTimer; private slots: void pathChanged(const QString &); + void notifyChangedPaths(); }; #endif