From ad23da4eda47a6bb05f7e614946976516d0666b5 Mon Sep 17 00:00:00 2001 From: zach Date: Mon, 25 May 2026 13:32:06 +0200 Subject: [PATCH] initial commit, primitive loading of QML code outside of shell directory --- Config/Config.qml | 13 +- Config/PluginConfig.qml | 11 + Extensions/FetchPlugins.qml | 18 + Extensions/LoadExtensions.qml | 17 + Helpers/Searcher.qml | 1 - Modules/Settings/Categories.qml | 6 + Modules/Settings/Categories/Plugins.qml | 18 + Modules/Settings/Content.qml | 9 + Plugins/ZShell/Models/filesystemmodel.cpp | 613 +++++++++++----------- Plugins/ZShell/Models/filesystemmodel.hpp | 190 +++---- shell.qml | 4 + 11 files changed, 492 insertions(+), 408 deletions(-) create mode 100644 Config/PluginConfig.qml create mode 100644 Extensions/FetchPlugins.qml create mode 100644 Extensions/LoadExtensions.qml create mode 100644 Modules/Settings/Categories/Plugins.qml diff --git a/Config/Config.qml b/Config/Config.qml index 2f6686e..f9b2d04 100644 --- a/Config/Config.qml +++ b/Config/Config.qml @@ -22,6 +22,7 @@ Singleton { property alias notifs: adapter.notifs property alias osd: adapter.osd property alias overview: adapter.overview + property alias plugins: adapter.plugins property bool recentlySaved: false property alias screenshot: adapter.screenshot property alias services: adapter.services @@ -140,7 +141,8 @@ Singleton { launcher: serializeLauncher(), colors: serializeColors(), dock: serializeDock(), - screenshot: serializeScreenshot() + screenshot: serializeScreenshot(), + plugins: serializePlugins() }; } @@ -289,6 +291,13 @@ Singleton { }; } + function serializePlugins(): var { + return { + enabled: plugins.enabled, + entries: plugins.entries + }; + } + function serializeScreenshot(): var { return { enable_pp: screenshot.enable_pp, @@ -458,6 +467,8 @@ Singleton { } property Overview overview: Overview { } + property PluginConfig plugins: PluginConfig { + } property Screenshot screenshot: Screenshot { } property Services services: Services { diff --git a/Config/PluginConfig.qml b/Config/PluginConfig.qml new file mode 100644 index 0000000..567eacb --- /dev/null +++ b/Config/PluginConfig.qml @@ -0,0 +1,11 @@ +import Quickshell.Io + +JsonObject { + property bool enabled: false + property list entries: [ + { + id: "Plugin", + enabled: false + }, + ] +} diff --git a/Extensions/FetchPlugins.qml b/Extensions/FetchPlugins.qml new file mode 100644 index 0000000..81ad282 --- /dev/null +++ b/Extensions/FetchPlugins.qml @@ -0,0 +1,18 @@ +pragma Singleton + +import Quickshell +import ZShell.Models + +Singleton { + id: root + + property alias plugins: plugins.entries + + FileSystemModel { + id: plugins + + nameFilters: ["*.qml"] + path: Quickshell.env("HOME") + "/.config/zshell" + recursive: false + } +} diff --git a/Extensions/LoadExtensions.qml b/Extensions/LoadExtensions.qml new file mode 100644 index 0000000..5d904af --- /dev/null +++ b/Extensions/LoadExtensions.qml @@ -0,0 +1,17 @@ +import Quickshell +import QtQuick +import ZShell.Models +import qs.Config + +Repeater { + model: FetchPlugins.plugins + + LazyLoader { + required property FileSystemEntry modelData + + activeAsync: Config.plugins.entries.some(p => { + return p.id === modelData.baseName && p.enabled; + }) + source: modelData.path + } +} diff --git a/Helpers/Searcher.qml b/Helpers/Searcher.qml index c6f5016..23f15e5 100644 --- a/Helpers/Searcher.qml +++ b/Helpers/Searcher.qml @@ -6,7 +6,6 @@ import Quickshell Singleton { property var extraOpts: ({}) readonly property list fuzzyPrepped: useFuzzy ? list.map(e => { - console.log(useFuzzy); const obj = { _item: e }; diff --git a/Modules/Settings/Categories.qml b/Modules/Settings/Categories.qml index df9875a..068e337 100644 --- a/Modules/Settings/Categories.qml +++ b/Modules/Settings/Categories.qml @@ -116,6 +116,12 @@ Item { key: "updates" name: "Updates" } + + ListElement { + icon: "extension" + key: "plugins" + name: "Extensions" + } } CustomClippingRect { diff --git a/Modules/Settings/Categories/Plugins.qml b/Modules/Settings/Categories/Plugins.qml new file mode 100644 index 0000000..92aceef --- /dev/null +++ b/Modules/Settings/Categories/Plugins.qml @@ -0,0 +1,18 @@ +import qs.Modules.Settings.Controls +import qs.Config + +SettingsPage { + SettingsSection { + sectionId: "Plugins" + + SettingsHeader { + name: "Plugins" + } + + SettingBarEntryList { + name: "Enable or disable plugins" + object: Config.plugins + setting: "entries" + } + } +} diff --git a/Modules/Settings/Content.qml b/Modules/Settings/Content.qml index 8759357..6150dc4 100644 --- a/Modules/Settings/Content.qml +++ b/Modules/Settings/Content.qml @@ -79,6 +79,8 @@ Item { stack.push(screenshot); else if (currentCategory === "updates") stack.push(updates); + else if (currentCategory === "plugins") + stack.push(plugins); } target: root @@ -245,4 +247,11 @@ Item { Cat.SystemUpdates { } } + + Component { + id: plugins + + Cat.Plugins { + } + } } diff --git a/Plugins/ZShell/Models/filesystemmodel.cpp b/Plugins/ZShell/Models/filesystemmodel.cpp index 790cefa..d38d03b 100644 --- a/Plugins/ZShell/Models/filesystemmodel.cpp +++ b/Plugins/ZShell/Models/filesystemmodel.cpp @@ -7,473 +7,464 @@ namespace ZShell::models { FileSystemEntry::FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent) - : QObject(parent) - , m_fileInfo(path) - , m_path(path) - , m_relativePath(relativePath) - , m_isImageInitialised(false) - , m_mimeTypeInitialised(false) {} + : QObject(parent) + , m_fileInfo(path) + , m_path(path) + , m_relativePath(relativePath) + , m_isImageInitialised(false) + , m_mimeTypeInitialised(false) { +} QString FileSystemEntry::path() const { - return m_path; + return m_path; }; QString FileSystemEntry::relativePath() const { - return m_relativePath; + return m_relativePath; }; QString FileSystemEntry::name() const { - return m_fileInfo.fileName(); + return m_fileInfo.fileName(); }; QString FileSystemEntry::baseName() const { - return m_fileInfo.baseName(); + return m_fileInfo.baseName(); }; QString FileSystemEntry::parentDir() const { - return m_fileInfo.absolutePath(); + return m_fileInfo.absolutePath(); }; QString FileSystemEntry::suffix() const { - return m_fileInfo.completeSuffix(); + return m_fileInfo.completeSuffix(); }; qint64 FileSystemEntry::size() const { - return m_fileInfo.size(); + return m_fileInfo.size(); }; bool FileSystemEntry::isDir() const { - return m_fileInfo.isDir(); + return m_fileInfo.isDir(); }; bool FileSystemEntry::isImage() const { - if (!m_isImageInitialised) { - QImageReader reader(m_path); - m_isImage = reader.canRead(); - m_isImageInitialised = true; - } - return m_isImage; + if (!m_isImageInitialised) { + QImageReader reader(m_path); + m_isImage = reader.canRead(); + m_isImageInitialised = true; + } + return m_isImage; } QString FileSystemEntry::mimeType() const { - if (!m_mimeTypeInitialised) { - const QMimeDatabase db; - m_mimeType = db.mimeTypeForFile(m_path).name(); - m_mimeTypeInitialised = true; - } - return m_mimeType; + if (!m_mimeTypeInitialised) { + static const QMimeDatabase s_db; + m_mimeType = s_db.mimeTypeForFile(m_path).name(); + m_mimeTypeInitialised = true; + } + return m_mimeType; } void FileSystemEntry::updateRelativePath(const QDir& dir) { - const auto relPath = dir.relativeFilePath(m_path); - if (m_relativePath != relPath) { - m_relativePath = relPath; - emit relativePathChanged(); - } + const auto relPath = dir.relativeFilePath(m_path); + if (m_relativePath != relPath) { + m_relativePath = relPath; + emit relativePathChanged(); + } } FileSystemModel::FileSystemModel(QObject* parent) - : QAbstractListModel(parent) - , m_recursive(false) - , m_watchChanges(true) - , m_showHidden(false) - , m_filter(NoFilter) { - connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive); - connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntriesForDir); + : QAbstractListModel(parent) + , m_recursive(false) + , m_watchChanges(true) + , m_showHidden(false) + , m_filter(NoFilter) { + connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive); + connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntriesForDir); } int FileSystemModel::rowCount(const QModelIndex& parent) const { - if (parent != QModelIndex()) { - return 0; - } - return static_cast(m_entries.size()); + if (parent != QModelIndex()) { + return 0; + } + return static_cast(m_entries.size()); } QVariant FileSystemModel::data(const QModelIndex& index, int role) const { - if (role != Qt::UserRole || !index.isValid() || index.row() >= m_entries.size()) { - return QVariant(); - } - return QVariant::fromValue(m_entries.at(index.row())); + if (role != Qt::UserRole || !index.isValid() || index.row() >= m_entries.size()) { + return QVariant(); + } + return QVariant::fromValue(m_entries.at(index.row())); } QHash FileSystemModel::roleNames() const { - return { { Qt::UserRole, "modelData" } }; + return { { Qt::UserRole, "modelData" } }; } QString FileSystemModel::path() const { - return m_path; + return m_path; } void FileSystemModel::setPath(const QString& path) { - if (m_path == path) { - return; - } + if (m_path == path) { + return; + } - m_path = path; - emit pathChanged(); + m_path = path; + emit pathChanged(); - m_dir.setPath(m_path); + m_dir.setPath(m_path); - for (const auto& entry : std::as_const(m_entries)) { - entry->updateRelativePath(m_dir); - } + for (const auto& entry : std::as_const(m_entries)) { + entry->updateRelativePath(m_dir); + } - update(); + update(); } bool FileSystemModel::recursive() const { - return m_recursive; + return m_recursive; } void FileSystemModel::setRecursive(bool recursive) { - if (m_recursive == recursive) { - return; - } + if (m_recursive == recursive) { + return; + } - m_recursive = recursive; - emit recursiveChanged(); + m_recursive = recursive; + emit recursiveChanged(); - update(); + update(); } bool FileSystemModel::watchChanges() const { - return m_watchChanges; + return m_watchChanges; } void FileSystemModel::setWatchChanges(bool watchChanges) { - if (m_watchChanges == watchChanges) { - return; - } + if (m_watchChanges == watchChanges) { + return; + } - m_watchChanges = watchChanges; - emit watchChangesChanged(); + m_watchChanges = watchChanges; + emit watchChangesChanged(); - update(); + update(); } bool FileSystemModel::showHidden() const { - return m_showHidden; + return m_showHidden; } void FileSystemModel::setShowHidden(bool showHidden) { - if (m_showHidden == showHidden) { - return; - } + if (m_showHidden == showHidden) { + return; + } - m_showHidden = showHidden; - emit showHiddenChanged(); + m_showHidden = showHidden; + emit showHiddenChanged(); - update(); + update(); } bool FileSystemModel::sortReverse() const { - return m_sortReverse; + return m_sortReverse; } void FileSystemModel::setSortReverse(bool sortReverse) { - if (m_sortReverse == sortReverse) { - return; - } + if (m_sortReverse == sortReverse) { + return; + } - m_sortReverse = sortReverse; - emit sortReverseChanged(); + m_sortReverse = sortReverse; + emit sortReverseChanged(); - update(); + update(); } FileSystemModel::Filter FileSystemModel::filter() const { - return m_filter; + return m_filter; } void FileSystemModel::setFilter(Filter filter) { - if (m_filter == filter) { - return; - } + if (m_filter == filter) { + return; + } - m_filter = filter; - emit filterChanged(); + m_filter = filter; + emit filterChanged(); - update(); + update(); } QStringList FileSystemModel::nameFilters() const { - return m_nameFilters; + return m_nameFilters; } void FileSystemModel::setNameFilters(const QStringList& nameFilters) { - if (m_nameFilters == nameFilters) { - return; - } + if (m_nameFilters == nameFilters) { + return; + } - m_nameFilters = nameFilters; - emit nameFiltersChanged(); + m_nameFilters = nameFilters; + emit nameFiltersChanged(); - update(); + update(); } QQmlListProperty FileSystemModel::entries() { - return QQmlListProperty(this, &m_entries); + return QQmlListProperty(this, &m_entries); } void FileSystemModel::watchDirIfRecursive(const QString& path) { - if (m_recursive && m_watchChanges) { - const auto currentDir = m_dir; - const bool showHidden = m_showHidden; - const auto future = QtConcurrent::run([showHidden, path]() { - QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot; - if (showHidden) { - filters |= QDir::Hidden; - } + if (m_recursive && m_watchChanges) { + const auto currentDir = m_dir; + const bool showHidden = m_showHidden; + auto future = QtConcurrent::run([showHidden, path]() { + QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot; + if (showHidden) { + filters |= QDir::Hidden; + } - QDirIterator iter(path, filters, QDirIterator::Subdirectories); - QStringList dirs; - while (iter.hasNext()) { - dirs << iter.next(); - } - return dirs; - }); - const auto watcher = new QFutureWatcher(this); - connect(watcher, &QFutureWatcher::finished, this, [currentDir, showHidden, watcher, this]() { - const auto paths = watcher->result(); - if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) { - // Ignore if dir or showHidden has changed - m_watcher.addPaths(paths); - } - watcher->deleteLater(); - }); - watcher->setFuture(future); - } + QDirIterator iter(path, filters, QDirIterator::Subdirectories); + QStringList dirs; + while (iter.hasNext()) { + dirs << iter.next(); + } + return dirs; + }); + future.then(this, [currentDir, showHidden, this](const QStringList& paths) { + if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) { + // Ignore if dir or showHidden has changed + m_watcher.addPaths(paths); + } + }); + } } void FileSystemModel::update() { - updateWatcher(); - updateEntries(); + updateWatcher(); + updateEntries(); } void FileSystemModel::updateWatcher() { - if (!m_watcher.directories().isEmpty()) { - m_watcher.removePaths(m_watcher.directories()); - } + if (!m_watcher.directories().isEmpty()) { + m_watcher.removePaths(m_watcher.directories()); + } - if (!m_watchChanges || m_path.isEmpty()) { - return; - } + if (!m_watchChanges || m_path.isEmpty()) { + return; + } - m_watcher.addPath(m_path); - watchDirIfRecursive(m_path); + m_watcher.addPath(m_path); + watchDirIfRecursive(m_path); } void FileSystemModel::updateEntries() { - if (m_path.isEmpty()) { - if (!m_entries.isEmpty()) { - beginResetModel(); - qDeleteAll(m_entries); - m_entries.clear(); - endResetModel(); - emit entriesChanged(); - } + if (m_path.isEmpty()) { + if (!m_entries.isEmpty()) { + beginResetModel(); + qDeleteAll(m_entries); + m_entries.clear(); + endResetModel(); + emit entriesChanged(); + } - return; - } + return; + } - for (auto& future : m_futures) { - future.cancel(); - } - m_futures.clear(); + for (auto& future : m_futures) { + future.cancel(); + } + m_futures.clear(); - updateEntriesForDir(m_path); + updateEntriesForDir(m_path); } void FileSystemModel::updateEntriesForDir(const QString& dir) { - const auto recursive = m_recursive; - const auto showHidden = m_showHidden; - const auto filter = m_filter; - const auto nameFilters = m_nameFilters; + const auto recursive = m_recursive; + const auto showHidden = m_showHidden; + const auto filter = m_filter; + const auto nameFilters = m_nameFilters; - QSet oldPaths; - for (const auto& entry : std::as_const(m_entries)) { - oldPaths << entry->path(); - } + QSet oldPaths; + for (const auto& entry : std::as_const(m_entries)) { + oldPaths << entry->path(); + } - const auto future = QtConcurrent::run([=](QPromise, QSet>>& promise) { - const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; + auto future = QtConcurrent::run([=](QPromise, QSet > >& promise) { + const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; - std::optional iter; + std::optional iter; - if (filter == Images) { - QStringList extraNameFilters = nameFilters; - const auto formats = QImageReader::supportedImageFormats(); - for (const auto& format : formats) { - extraNameFilters << "*." + format; - } + if (filter == Images) { + QStringList extraNameFilters = nameFilters; + const auto formats = QImageReader::supportedImageFormats(); + for (const auto& format : formats) { + extraNameFilters << "*." + format; + } - QDir::Filters filters = QDir::Files; - if (showHidden) { - filters |= QDir::Hidden; - } + QDir::Filters filters = QDir::Files; + if (showHidden) { + filters |= QDir::Hidden; + } - iter.emplace(dir, extraNameFilters, filters, flags); - } else { - QDir::Filters filters; + iter.emplace(dir, extraNameFilters, filters, flags); + } else { + QDir::Filters filters; - if (filter == Files) { - filters = QDir::Files; - } else if (filter == Dirs) { - filters = QDir::Dirs | QDir::NoDotAndDotDot; - } else { - filters = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot; - } + if (filter == Files) { + filters = QDir::Files; + } else if (filter == Dirs) { + filters = QDir::Dirs | QDir::NoDotAndDotDot; + } else { + filters = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot; + } - if (showHidden) { - filters |= QDir::Hidden; - } + if (showHidden) { + filters |= QDir::Hidden; + } - if (nameFilters.isEmpty()) { - iter.emplace(dir, filters, flags); - } else { - iter.emplace(dir, nameFilters, filters, flags); - } - } + if (nameFilters.isEmpty()) { + iter.emplace(dir, filters, flags); + } else { + iter.emplace(dir, nameFilters, filters, flags); + } + } - QSet newPaths; - while (iter->hasNext()) { - if (promise.isCanceled()) { - return; - } + QSet newPaths; + while (iter->hasNext()) { + if (promise.isCanceled()) { + return; + } - QString path = iter->next(); + QString path = iter->next(); - if (filter == Images) { - QImageReader reader(path); - if (!reader.canRead()) { - continue; - } - } + if (filter == Images) { + QImageReader reader(path); + if (!reader.canRead()) { + continue; + } + } - newPaths.insert(path); - } + newPaths.insert(path); + } - if (promise.isCanceled() || newPaths == oldPaths) { - return; - } + if (promise.isCanceled()) { + return; + } - promise.addResult(qMakePair(oldPaths - newPaths, newPaths - oldPaths)); - }); + promise.addResult(qMakePair(oldPaths - newPaths, newPaths - oldPaths)); + }); - if (m_futures.contains(dir)) { - m_futures[dir].cancel(); - } - m_futures.insert(dir, future); + if (m_futures.contains(dir)) { + m_futures[dir].cancel(); + } + m_futures.insert(dir, future); - const auto watcher = new QFutureWatcher, QSet>>(this); - - connect(watcher, &QFutureWatcher, QSet>>::finished, this, [dir, watcher, this]() { - m_futures.remove(dir); - - if (!watcher->future().isResultReadyAt(0)) { - watcher->deleteLater(); - return; - } - - const auto result = watcher->result(); - applyChanges(result.first, result.second); - - watcher->deleteLater(); - }); - - watcher->setFuture(future); + future + .then(this, + [dir, this](QPair, QSet > result) { + m_futures.remove(dir); + if (!result.first.isEmpty() || !result.second.isEmpty()) { + applyChanges(result.first, result.second); + } + }) + .onCanceled(this, [dir, this]() { + m_futures.remove(dir); + }); } void FileSystemModel::applyChanges(const QSet& removedPaths, const QSet& addedPaths) { - QList removedIndices; - for (int i = 0; i < m_entries.size(); ++i) { - if (removedPaths.contains(m_entries[i]->path())) { - removedIndices << i; - } - } - std::sort(removedIndices.begin(), removedIndices.end(), std::greater()); + QList removedIndices; + for (int i = 0; i < m_entries.size(); ++i) { + if (removedPaths.contains(m_entries[i]->path())) { + removedIndices << i; + } + } + std::sort(removedIndices.begin(), removedIndices.end(), std::greater()); - // Batch remove old entries - int start = -1; - int end = -1; - for (int idx : std::as_const(removedIndices)) { - if (start == -1) { - start = idx; - end = idx; - } else if (idx == end - 1) { - end = idx; - } else { - beginRemoveRows(QModelIndex(), end, start); - for (int i = start; i >= end; --i) { - m_entries.takeAt(i)->deleteLater(); - } - endRemoveRows(); + // Batch remove old entries + int start = -1; + int end = -1; + for (int idx : std::as_const(removedIndices)) { + if (start == -1) { + start = idx; + end = idx; + } else if (idx == end - 1) { + end = idx; + } else { + beginRemoveRows(QModelIndex(), end, start); + for (int i = start; i >= end; --i) { + m_entries.takeAt(i)->deleteLater(); + } + endRemoveRows(); - start = idx; - end = idx; - } - } - if (start != -1) { - beginRemoveRows(QModelIndex(), end, start); - for (int i = start; i >= end; --i) { - m_entries.takeAt(i)->deleteLater(); - } - endRemoveRows(); - } + start = idx; + end = idx; + } + } + if (start != -1) { + beginRemoveRows(QModelIndex(), end, start); + for (int i = start; i >= end; --i) { + m_entries.takeAt(i)->deleteLater(); + } + endRemoveRows(); + } - // Create new entries - QList newEntries; - for (const auto& path : addedPaths) { - newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this); - } - std::sort(newEntries.begin(), newEntries.end(), [this](const FileSystemEntry* a, const FileSystemEntry* b) { - return compareEntries(a, b); - }); + // Create new entries + QList newEntries; + for (const auto& path : addedPaths) { + newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this); + } + std::sort(newEntries.begin(), newEntries.end(), [this](const FileSystemEntry* a, const FileSystemEntry* b) { + return compareEntries(a, b); + }); - // Batch insert new entries - int insertStart = -1; - QList batchItems; - for (const auto& entry : std::as_const(newEntries)) { - const auto it = std::lower_bound( - m_entries.begin(), m_entries.end(), entry, [this](const FileSystemEntry* a, const FileSystemEntry* b) { - return compareEntries(a, b); - }); - const auto row = static_cast(it - m_entries.begin()); + // Batch insert new entries + int insertStart = -1; + QList batchItems; + for (const auto& entry : std::as_const(newEntries)) { + const auto it = std::lower_bound( + m_entries.begin(), m_entries.end(), entry, [this](const FileSystemEntry* a, const FileSystemEntry* b) { + return compareEntries(a, b); + }); + const auto row = static_cast(it - m_entries.begin()); - if (insertStart == -1) { - insertStart = row; - batchItems << entry; - } else if (row == insertStart + batchItems.size()) { - batchItems << entry; - } else { - beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast(batchItems.size()) - 1); - for (int i = 0; i < batchItems.size(); ++i) { - m_entries.insert(insertStart + i, batchItems[i]); - } - endInsertRows(); + if (insertStart == -1) { + insertStart = row; + batchItems << entry; + } else if (row == insertStart + batchItems.size()) { + batchItems << entry; + } else { + beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast(batchItems.size()) - 1); + for (int i = 0; i < batchItems.size(); ++i) { + m_entries.insert(insertStart + i, batchItems[i]); + } + endInsertRows(); - insertStart = row; - batchItems.clear(); - batchItems << entry; - } - } - if (!batchItems.isEmpty()) { - beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast(batchItems.size()) - 1); - for (int i = 0; i < batchItems.size(); ++i) { - m_entries.insert(insertStart + i, batchItems[i]); - } - endInsertRows(); - } + insertStart = row; + batchItems.clear(); + batchItems << entry; + } + } + if (!batchItems.isEmpty()) { + beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast(batchItems.size()) - 1); + for (int i = 0; i < batchItems.size(); ++i) { + m_entries.insert(insertStart + i, batchItems[i]); + } + endInsertRows(); + } - emit entriesChanged(); + emit entriesChanged(); } bool FileSystemModel::compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const { - if (a->isDir() != b->isDir()) { - return m_sortReverse ^ a->isDir(); - } - const auto cmp = a->relativePath().localeAwareCompare(b->relativePath()); - return m_sortReverse ? cmp > 0 : cmp < 0; + if (a->isDir() != b->isDir()) { + return m_sortReverse ^ a->isDir(); + } + const auto cmp = a->relativePath().localeAwareCompare(b->relativePath()); + return m_sortReverse ? cmp > 0 : cmp < 0; } } // namespace ZShell::models diff --git a/Plugins/ZShell/Models/filesystemmodel.hpp b/Plugins/ZShell/Models/filesystemmodel.hpp index f2bbfcd..d41282a 100644 --- a/Plugins/ZShell/Models/filesystemmodel.hpp +++ b/Plugins/ZShell/Models/filesystemmodel.hpp @@ -13,136 +13,136 @@ namespace ZShell::models { class FileSystemEntry : public QObject { - Q_OBJECT - QML_ELEMENT - QML_UNCREATABLE("FileSystemEntry instances can only be retrieved from a FileSystemModel") +Q_OBJECT +QML_ELEMENT + QML_UNCREATABLE("FileSystemEntry instances can only be retrieved from a FileSystemModel") - Q_PROPERTY(QString path READ path CONSTANT) - Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged) - Q_PROPERTY(QString name READ name CONSTANT) - Q_PROPERTY(QString baseName READ baseName CONSTANT) - Q_PROPERTY(QString parentDir READ parentDir CONSTANT) - Q_PROPERTY(QString suffix READ suffix CONSTANT) - Q_PROPERTY(qint64 size READ size CONSTANT) - Q_PROPERTY(bool isDir READ isDir CONSTANT) - Q_PROPERTY(bool isImage READ isImage CONSTANT) - Q_PROPERTY(QString mimeType READ mimeType CONSTANT) +Q_PROPERTY(QString path READ path CONSTANT) +Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged) +Q_PROPERTY(QString name READ name CONSTANT) +Q_PROPERTY(QString baseName READ baseName CONSTANT) +Q_PROPERTY(QString parentDir READ parentDir CONSTANT) +Q_PROPERTY(QString suffix READ suffix CONSTANT) +Q_PROPERTY(qint64 size READ size CONSTANT) +Q_PROPERTY(bool isDir READ isDir CONSTANT) +Q_PROPERTY(bool isImage READ isImage CONSTANT) +Q_PROPERTY(QString mimeType READ mimeType CONSTANT) public: - explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr); +explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr); - [[nodiscard]] QString path() const; - [[nodiscard]] QString relativePath() const; - [[nodiscard]] QString name() const; - [[nodiscard]] QString baseName() const; - [[nodiscard]] QString parentDir() const; - [[nodiscard]] QString suffix() const; - [[nodiscard]] qint64 size() const; - [[nodiscard]] bool isDir() const; - [[nodiscard]] bool isImage() const; - [[nodiscard]] QString mimeType() const; +[[nodiscard]] QString path() const; +[[nodiscard]] QString relativePath() const; +[[nodiscard]] QString name() const; +[[nodiscard]] QString baseName() const; +[[nodiscard]] QString parentDir() const; +[[nodiscard]] QString suffix() const; +[[nodiscard]] qint64 size() const; +[[nodiscard]] bool isDir() const; +[[nodiscard]] bool isImage() const; +[[nodiscard]] QString mimeType() const; - void updateRelativePath(const QDir& dir); +void updateRelativePath(const QDir& dir); signals: - void relativePathChanged(); +void relativePathChanged(); private: - const QFileInfo m_fileInfo; +const QFileInfo m_fileInfo; - const QString m_path; - QString m_relativePath; +const QString m_path; +QString m_relativePath; - mutable bool m_isImage; - mutable bool m_isImageInitialised; +mutable bool m_isImage; +mutable bool m_isImageInitialised; - mutable QString m_mimeType; - mutable bool m_mimeTypeInitialised; +mutable QString m_mimeType; +mutable bool m_mimeTypeInitialised; }; class FileSystemModel : public QAbstractListModel { - Q_OBJECT - QML_ELEMENT +Q_OBJECT +QML_ELEMENT - Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) - Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) - Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged) - Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged) - Q_PROPERTY(bool sortReverse READ sortReverse WRITE setSortReverse NOTIFY sortReverseChanged) - Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged) - Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) +Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) +Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) +Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged) +Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged) +Q_PROPERTY(bool sortReverse READ sortReverse WRITE setSortReverse NOTIFY sortReverseChanged) +Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged) +Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) - Q_PROPERTY(QQmlListProperty entries READ entries NOTIFY entriesChanged) +Q_PROPERTY(QQmlListProperty entries READ entries NOTIFY entriesChanged) public: - enum Filter { - NoFilter, - Images, - Files, - Dirs - }; - Q_ENUM(Filter) +enum Filter { + NoFilter, + Images, + Files, + Dirs +}; +Q_ENUM(Filter) - explicit FileSystemModel(QObject* parent = nullptr); +explicit FileSystemModel(QObject* parent = nullptr); - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - QHash roleNames() const override; +int rowCount(const QModelIndex& parent = QModelIndex()) const override; +QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; +QHash roleNames() const override; - [[nodiscard]] QString path() const; - void setPath(const QString& path); +[[nodiscard]] QString path() const; +void setPath(const QString& path); - [[nodiscard]] bool recursive() const; - void setRecursive(bool recursive); +[[nodiscard]] bool recursive() const; +void setRecursive(bool recursive); - [[nodiscard]] bool watchChanges() const; - void setWatchChanges(bool watchChanges); +[[nodiscard]] bool watchChanges() const; +void setWatchChanges(bool watchChanges); - [[nodiscard]] bool showHidden() const; - void setShowHidden(bool showHidden); +[[nodiscard]] bool showHidden() const; +void setShowHidden(bool showHidden); - [[nodiscard]] bool sortReverse() const; - void setSortReverse(bool sortReverse); +[[nodiscard]] bool sortReverse() const; +void setSortReverse(bool sortReverse); - [[nodiscard]] Filter filter() const; - void setFilter(Filter filter); +[[nodiscard]] Filter filter() const; +void setFilter(Filter filter); - [[nodiscard]] QStringList nameFilters() const; - void setNameFilters(const QStringList& nameFilters); +[[nodiscard]] QStringList nameFilters() const; +void setNameFilters(const QStringList& nameFilters); - [[nodiscard]] QQmlListProperty entries(); +[[nodiscard]] QQmlListProperty entries(); signals: - void pathChanged(); - void recursiveChanged(); - void watchChangesChanged(); - void showHiddenChanged(); - void sortReverseChanged(); - void filterChanged(); - void nameFiltersChanged(); - void entriesChanged(); +void pathChanged(); +void recursiveChanged(); +void watchChangesChanged(); +void showHiddenChanged(); +void sortReverseChanged(); +void filterChanged(); +void nameFiltersChanged(); +void entriesChanged(); private: - QDir m_dir; - QFileSystemWatcher m_watcher; - QList m_entries; - QHash, QSet>>> m_futures; +QDir m_dir; +QFileSystemWatcher m_watcher; +QList m_entries; +QHash, QSet > > > m_futures; - QString m_path; - bool m_recursive; - bool m_watchChanges; - bool m_showHidden; - bool m_sortReverse; - Filter m_filter; - QStringList m_nameFilters; +QString m_path; +bool m_recursive; +bool m_watchChanges; +bool m_showHidden; +bool m_sortReverse = false; +Filter m_filter; +QStringList m_nameFilters; - void watchDirIfRecursive(const QString& path); - void update(); - void updateWatcher(); - void updateEntries(); - void updateEntriesForDir(const QString& dir); - void applyChanges(const QSet& removedPaths, const QSet& addedPaths); - [[nodiscard]] bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const; +void watchDirIfRecursive(const QString& path); +void update(); +void updateWatcher(); +void updateEntries(); +void updateEntriesForDir(const QString& dir); +void applyChanges(const QSet& removedPaths, const QSet& addedPaths); +[[nodiscard]] bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const; }; } // namespace ZShell::models diff --git a/shell.qml b/shell.qml index 90f6efa..69ac70c 100644 --- a/shell.qml +++ b/shell.qml @@ -6,6 +6,7 @@ //@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round //@ pragma DropExpensiveFonts import Quickshell +import qs.Extensions import qs.Modules import qs.Modules.Wallpaper import qs.Modules.Lock @@ -38,4 +39,7 @@ ShellRoot { Polkit { } + + LoadExtensions { + } }