From f196da3aa5e15aeb95762ce4d97ec54269c16959 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 12 Sep 2017 12:25:54 +0200 Subject: democompositor: Remove deleted files from the model In the previous code review Paul discovered the fact that files would never be removed. Implement finding deleted files and emit a signal per removed file. Consume the signal in QML and use the new API to kill the process (one could close the wayland display connection as well). Emit the removed signals _after_ the model has been updated to provide the QML code with an updated model during the signal handling. Change-Id: Ib3bb1bd953bfbf09d25c5e5822756a53b08fd797 Reviewed-by: Paul Olav Tvete --- wayland/democompositor/apps/applistmodel.cpp | 59 +++++++++++++++++++++++++--- wayland/democompositor/apps/applistmodel.h | 7 +++- wayland/democompositor/qml/Screen.qml | 4 ++ 3 files changed, 64 insertions(+), 6 deletions(-) (limited to 'wayland') diff --git a/wayland/democompositor/apps/applistmodel.cpp b/wayland/democompositor/apps/applistmodel.cpp index 0b4d620..b0774f7 100644 --- a/wayland/democompositor/apps/applistmodel.cpp +++ b/wayland/democompositor/apps/applistmodel.cpp @@ -135,25 +135,74 @@ void AppListModel::addDir(const QString& dirName) { QDirIterator dirIt(dirName, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable); + // We want to deal with the corner case of some files being + // removed. One option would have been to keep a marker bit + // inside the AppEntry but that might leak too much of the + // implementation to the outside. Let's keep a list of file + // names that came from the directory and remove items from + // the list as we re-parse them. Once we are done emit the + // signals. + QVector deletionCandidates = entriesWithPrefix(dirName); + beginResetModel(); - while (dirIt.hasNext()) - doAddFile(dirIt.next()); + while (dirIt.hasNext()) { + auto fileName = dirIt.next(); + if (!doAddFile(fileName)) + continue; + deletionCandidates.removeAll(fileName); + } + QVector removedApps = removeEntries(deletionCandidates); endResetModel(); + + // Announce the apps we removed after the model has been updated + for (const auto& app : removedApps) { + qCDebug(apps) << "Going to remove entry for " << app.sourceFileName; + emit appRemoved(app); + } } -void AppListModel::doAddFile(const QString& fileName) +bool AppListModel::doAddFile(const QString& fileName) { bool ok; auto newEntry = AppParser::parseFile(fileName, &ok); if (!ok) - return; + return false; for (int i = 0; i < m_rows.count(); ++i) { if (m_rows[i].sourceFileName == fileName) { m_rows[i] = newEntry; - return; + return true; } } m_rows.push_back(newEntry); + return true; +} + +QVector AppListModel::entriesWithPrefix(const QString& prefix) const +{ + QVector entries; + + for (const AppEntry& entry : m_rows) + if (entry.sourceFileName.startsWith(prefix)) + entries.push_back(entry.sourceFileName); + return entries; +} + +QVector AppListModel::removeEntries(const QVector& fileNames) +{ + QVector removedEntries(fileNames.size()); + + // Rare but quadratic. The actual removal. + for (const auto &toRemoveFile: fileNames) { + for (int i = 0; i < m_rows.size(); ++i) { + if (m_rows[i].sourceFileName != toRemoveFile) + continue; + removedEntries.append(m_rows[i]); + m_rows.removeAt(i); + break; + } + } + + return removedEntries; } diff --git a/wayland/democompositor/apps/applistmodel.h b/wayland/democompositor/apps/applistmodel.h index 9147f54..4662e8f 100644 --- a/wayland/democompositor/apps/applistmodel.h +++ b/wayland/democompositor/apps/applistmodel.h @@ -76,6 +76,9 @@ public: QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE; QHash roleNames() const Q_DECL_OVERRIDE; +Q_SIGNALS: + void appRemoved(const AppEntry& appEntry); + public Q_SLOTS: bool addAndWatchDir(const QString& dirName); @@ -83,7 +86,9 @@ public Q_SLOTS: void addDir(const QString& dirName); private: - void doAddFile(const QString& fileName); + QVector entriesWithPrefix(const QString& prefix) const; + QVector removeEntries(const QVector& sourceFileNames); + bool doAddFile(const QString& fileName); QVector m_rows; static QHash m_roles; diff --git a/wayland/democompositor/qml/Screen.qml b/wayland/democompositor/qml/Screen.qml index ffb8490..7ab7481 100644 --- a/wayland/democompositor/qml/Screen.qml +++ b/wayland/democompositor/qml/Screen.qml @@ -89,6 +89,10 @@ WaylandOutput { AppListModel { id: apps + onAppRemoved: { + console.log("Application was removed: " + appEntry.appName); + launcher.stop(appEntry); + } } Component.onCompleted: { -- cgit v1.2.3