diff options
Diffstat (limited to 'wayland')
-rw-r--r-- | wayland/democompositor/apps/applistmodel.cpp | 59 | ||||
-rw-r--r-- | wayland/democompositor/apps/applistmodel.h | 7 | ||||
-rw-r--r-- | wayland/democompositor/qml/Screen.qml | 4 |
3 files changed, 64 insertions, 6 deletions
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<QString> 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<AppEntry> 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<QString> AppListModel::entriesWithPrefix(const QString& prefix) const +{ + QVector<QString> entries; + + for (const AppEntry& entry : m_rows) + if (entry.sourceFileName.startsWith(prefix)) + entries.push_back(entry.sourceFileName); + return entries; +} + +QVector<AppEntry> AppListModel::removeEntries(const QVector<QString>& fileNames) +{ + QVector<AppEntry> 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<int, QByteArray> 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<QString> entriesWithPrefix(const QString& prefix) const; + QVector<AppEntry> removeEntries(const QVector<QString>& sourceFileNames); + bool doAddFile(const QString& fileName); QVector<AppEntry> m_rows; static QHash<int, QByteArray> 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: { |