diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-09-11 02:03:01 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-09-11 02:03:01 +1000 |
| commit | 2832de18d71579383b400c1bf9ecbcb0ef54ce10 (patch) | |
| tree | 62237ba1a81b243e5a1f2e3ae86d9fb9d802b4bf /plugin/src/Caelestia/appdb.cpp | |
| parent | plugin: remove multimedia dep (diff) | |
| download | caelestia-shell-2832de18d71579383b400c1bf9ecbcb0ef54ce10.tar.gz caelestia-shell-2832de18d71579383b400c1bf9ecbcb0ef54ce10.tar.bz2 caelestia-shell-2832de18d71579383b400c1bf9ecbcb0ef54ce10.zip | |
launcher: sort apps by usage
Closes #588
Diffstat (limited to 'plugin/src/Caelestia/appdb.cpp')
| -rw-r--r-- | plugin/src/Caelestia/appdb.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/plugin/src/Caelestia/appdb.cpp b/plugin/src/Caelestia/appdb.cpp new file mode 100644 index 0000000..20e37bb --- /dev/null +++ b/plugin/src/Caelestia/appdb.cpp @@ -0,0 +1,201 @@ +#include "appdb.hpp" + +#include <qsqldatabase.h> +#include <qsqlquery.h> +#include <quuid.h> + +namespace caelestia { + +AppEntry::AppEntry(QObject* entry, unsigned int frequency, QObject* parent) + : QObject(parent) + , m_entry(entry) + , m_frequency(frequency) {} + +QObject* AppEntry::entry() const { + return m_entry; +} + +quint32 AppEntry::frequency() const { + return m_frequency; +} + +void AppEntry::setFrequency(unsigned int frequency) { + if (m_frequency != frequency) { + m_frequency = frequency; + emit frequencyChanged(); + } +} + +void AppEntry::incrementFrequency() { + m_frequency++; + emit frequencyChanged(); +} + +QString AppEntry::id() const { + return m_entry->property("id").toString(); +} + +QString AppEntry::name() const { + return m_entry->property("name").toString(); +} + +QString AppEntry::desc() const { + return m_entry->property("comment").toString(); +} + +QString AppEntry::execString() const { + return m_entry->property("execString").toString(); +} + +QString AppEntry::wmClass() const { + return m_entry->property("startupClass").toString(); +} + +QString AppEntry::genericName() const { + return m_entry->property("genericName").toString(); +} + +QString AppEntry::categories() const { + return m_entry->property("categories").toStringList().join(" "); +} + +QString AppEntry::keywords() const { + return m_entry->property("keywords").toStringList().join(" "); +} + +AppDb::AppDb(QObject* parent) + : QObject(parent) + , m_uuid(QUuid::createUuid().toString()) { + auto db = QSqlDatabase::addDatabase("QSQLITE", m_uuid); + db.setDatabaseName(":memory:"); + db.open(); + + QSqlQuery query(db); + query.exec("CREATE TABLE IF NOT EXISTS frequencies (id TEXT PRIMARY KEY, frequency INTEGER)"); +} + +QString AppDb::uuid() const { + return m_uuid; +} + +QString AppDb::path() const { + return m_path; +} + +void AppDb::setPath(const QString& path) { + if (m_path == path) { + return; + } + + m_path = path; + emit pathChanged(); + + auto db = QSqlDatabase::database(m_uuid, false); + db.close(); + db.setDatabaseName(path); + + updateAppFrequencies(); +} + +QList<QObject*> AppDb::entries() const { + return m_entries; +} + +void AppDb::setEntries(const QList<QObject*>& entries) { + if (m_entries == entries) { + return; + } + + m_entries = entries; + emit entriesChanged(); + + updateApps(); +} + +QList<AppEntry*> AppDb::apps() const { + auto apps = m_apps.values(); + std::sort(apps.begin(), apps.end(), [](AppEntry* a, AppEntry* b) { + if (a->frequency() != b->frequency()) { + return a->frequency() > b->frequency(); + } + return a->name().localeAwareCompare(b->name()) < 0; + }); + return apps; +} + +void AppDb::incrementFrequency(const QString& id) { + auto db = QSqlDatabase::database(m_uuid); + QSqlQuery query(db); + + query.prepare("INSERT INTO frequencies (id, frequency) " + "VALUES (:id, 1) " + "ON CONFLICT (id) DO UPDATE SET frequency = frequency + 1"); + query.bindValue(":id", id); + query.exec(); + + for (auto app : m_apps) { + if (app->id() == id) { + const auto before = apps(); + + app->incrementFrequency(); + + if (before != apps()) { + emit appsChanged(); + } + + return; + } + } + + qWarning() << "AppDb::incrementFrequency: could not find app with id" << id; +} + +quint32 AppDb::getFrequency(const QString& id) const { + auto db = QSqlDatabase::database(m_uuid); + QSqlQuery query(db); + + query.prepare("SELECT frequency FROM frequencies WHERE id = :id"); + query.bindValue(":id", id); + + if (query.exec() && query.next()) { + return query.value(0).toUInt(); + } + + return 0; +} + +void AppDb::updateAppFrequencies() { + for (auto app : m_apps) { + app->setFrequency(getFrequency(app->id())); + } +} + +void AppDb::updateApps() { + bool dirty = false; + + for (auto entry : m_entries) { + const auto id = entry->property("id").toString(); + if (!m_apps.contains(id)) { + dirty = true; + m_apps.insert(id, new AppEntry(entry, getFrequency(id), this)); + } + } + + QSet<QString> newIds; + for (auto entry : m_entries) { + newIds.insert(entry->property("id").toString()); + } + + for (auto id : m_apps.keys()) { + if (!newIds.contains(id)) { + dirty = true; + delete m_apps.take(id); + } + } + + if (dirty) { + emit appsChanged(); + } +} + +} // namespace caelestia |