Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
d39e36e096
|
|||
| cf73b12996 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(WallReel VERSION 2.1.0 LANGUAGES CXX)
|
||||
project(WallReel VERSION 2.2.0 LANGUAGES CXX)
|
||||
|
||||
set(EXECUTABLE_NAME "wallreel")
|
||||
set(CORELIB_NAME "wallreel-core")
|
||||
|
||||
@@ -121,7 +121,7 @@ Configures system commands to execute on specific events mapping to your window
|
||||
| `onPreview` | String | `""` | Command to execute when a wallpaper is previewed. |
|
||||
| `saveState` | Array of Objects | `[]` | Commands to fetch system states before changing wallpapers. Each object defines: `key`, `fallback` (fallback value), `command` (stdout mapping), and `timeout` (ms). |
|
||||
| `onRestore` | String | `""` | Command to execute on restore. Extracted states from `saveState` can be injected using `{{ key }}`. |
|
||||
| `quitOnSelected` | Boolean | `false` | Quit the application after a selection is made. |
|
||||
| `quitOnSelected` | Boolean | `true` | Quit the application after a selection is made. |
|
||||
| `restoreOnClose` | Boolean | `true` | Run `onRestore` command if the application is closed without making a final selection. |
|
||||
|
||||
Available placeholders for `onSelected`, `onPreview` commands:
|
||||
|
||||
@@ -97,7 +97,7 @@ Each item has:
|
||||
executed on restore.
|
||||
Saved state keys are usable as placeholders.
|
||||
.PP
|
||||
\f[CR]quitOnSelected\f[R] (boolean, default: \f[CR]false\f[R]) : Exit
|
||||
\f[CR]quitOnSelected\f[R] (boolean, default: \f[CR]true\f[R]) : Exit
|
||||
application immediately after confirming a selection.
|
||||
.PP
|
||||
\f[CR]restoreOnClose\f[R] (boolean, default: \f[CR]true\f[R]) : Run
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
// action.saveState[].command string "" Command that outputs(to stdout) the value to save when executed
|
||||
// action.saveState[].timeout number 3000 Timeout for executing "command" in milliseconds. 0 or negative means no timeout
|
||||
// action.onRestore string "" Command to execute on restore ({{ key }} -> value defined or obtained in saveState)
|
||||
// action.quitOnSelected boolean false Whether to quit the application after confirming a wallpaper
|
||||
// action.quitOnSelected boolean true Whether to quit the application after confirming a wallpaper
|
||||
// action.restoreOnClose boolean true Whether to run the restore command after closing the application without confirming a wallpaper
|
||||
//
|
||||
// style.image_width number 320 Width of each image
|
||||
@@ -125,7 +125,7 @@ struct ActionConfigItems {
|
||||
QString onRestore;
|
||||
int previewDebounceTime = 300; // milliseconds
|
||||
bool printSelected = true;
|
||||
bool quitOnSelected = false;
|
||||
bool quitOnSelected = true;
|
||||
bool restoreOnClose = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -54,9 +54,6 @@ Manager::Manager(
|
||||
WR_INFO(QString("No search directories specified, using Pictures directory: %1").arg(picturesPath));
|
||||
m_wallpaperConfig.dirs.append({picturesPath, true});
|
||||
}
|
||||
|
||||
WR_DEBUG("Loading wallpapers ...");
|
||||
_loadWallpapers();
|
||||
}
|
||||
|
||||
Manager::~Manager() {
|
||||
@@ -324,7 +321,7 @@ void Manager::_loadCacheConfig(const QJsonObject& root) {
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::_loadWallpapers() {
|
||||
void Manager::scanWallpapers() {
|
||||
m_wallpapers.clear();
|
||||
|
||||
// Add paths first using a set to avoid duplicates
|
||||
|
||||
@@ -72,6 +72,8 @@ class Manager : public QObject {
|
||||
*/
|
||||
Q_INVOKABLE void captureState();
|
||||
|
||||
void scanWallpapers();
|
||||
|
||||
signals:
|
||||
void stateCaptured();
|
||||
|
||||
@@ -83,8 +85,6 @@ class Manager : public QObject {
|
||||
void _loadActionConfig(const QJsonObject& config);
|
||||
void _loadStyleConfig(const QJsonObject& config);
|
||||
void _loadCacheConfig(const QJsonObject& config);
|
||||
// Load wallpapers
|
||||
void _loadWallpapers();
|
||||
// Callback for state capture results
|
||||
void _onCaptureResult(const QString& key, const QString& value);
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
WALLREEL_DECLARE_SENDER("ImageManager")
|
||||
|
||||
WallReel::Core::Image::Manager::Manager(
|
||||
Config::Manager& configMgr,
|
||||
Cache::Manager& cacheMgr,
|
||||
const QSize& thumbnailSize,
|
||||
QObject* parent)
|
||||
: QObject(parent),
|
||||
m_configMgr(configMgr),
|
||||
m_cacheMgr(cacheMgr),
|
||||
m_thumbnailSize(thumbnailSize) {
|
||||
m_dataModel = new Model(this);
|
||||
@@ -38,6 +40,21 @@ WallReel::Core::Image::Manager::~Manager() {
|
||||
m_watcher.waitForFinished();
|
||||
}
|
||||
|
||||
void WallReel::Core::Image::Manager::loadAndProcess() {
|
||||
if (m_isLoading) {
|
||||
WR_WARN("Already loading images. Ignoring new load request.");
|
||||
return;
|
||||
}
|
||||
m_isLoading = true;
|
||||
emit isLoadingChanged();
|
||||
|
||||
_clearData();
|
||||
|
||||
m_configMgr.scanWallpapers();
|
||||
const auto paths = m_configMgr.getWallpapers();
|
||||
return _process(paths);
|
||||
}
|
||||
|
||||
void WallReel::Core::Image::Manager::loadAndProcess(const QStringList& paths) {
|
||||
if (m_isLoading) {
|
||||
WR_WARN("Already loading images. Ignoring new load request.");
|
||||
@@ -48,6 +65,10 @@ void WallReel::Core::Image::Manager::loadAndProcess(const QStringList& paths) {
|
||||
|
||||
_clearData();
|
||||
|
||||
return _process(paths);
|
||||
}
|
||||
|
||||
void WallReel::Core::Image::Manager::_process(const QStringList& paths) {
|
||||
m_processedCount = 0;
|
||||
m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs);
|
||||
// These are all small objects so capturing by value should be fine
|
||||
@@ -75,6 +96,7 @@ void WallReel::Core::Image::Manager::stop() {
|
||||
|
||||
void WallReel::Core::Image::Manager::_clearData() {
|
||||
m_dataModel->clearData();
|
||||
m_dataMap.clear();
|
||||
}
|
||||
|
||||
void WallReel::Core::Image::Manager::_onProgressValueChanged(int value) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "Cache/manager.hpp"
|
||||
#include "Config/manager.hpp"
|
||||
#include "data.hpp"
|
||||
#include "model.hpp"
|
||||
|
||||
@@ -20,6 +21,7 @@ class Manager : public QObject {
|
||||
// Constructor / Destructor
|
||||
|
||||
Manager(
|
||||
Config::Manager& configMgr,
|
||||
Cache::Manager& cacheMgr,
|
||||
const QSize& thumbnailSize,
|
||||
QObject* parent = nullptr);
|
||||
@@ -32,6 +34,8 @@ class Manager : public QObject {
|
||||
|
||||
int processedCount() const { return m_processedCount.load(std::memory_order_relaxed); }
|
||||
|
||||
// Total count of processing items, NOT the count of items in the model
|
||||
// (Why did I name this method like this? idk)
|
||||
int totalCount() const { return m_watcher.progressMaximum(); }
|
||||
|
||||
void setSortType(Config::SortType type) { m_proxyModel->setSortType(type); }
|
||||
@@ -46,6 +50,8 @@ class Manager : public QObject {
|
||||
|
||||
QString searchText() const { return m_proxyModel->getSearchText(); }
|
||||
|
||||
void loadAndProcess();
|
||||
|
||||
void loadAndProcess(const QStringList& paths);
|
||||
|
||||
void stop();
|
||||
@@ -59,6 +65,7 @@ class Manager : public QObject {
|
||||
|
||||
private:
|
||||
void _clearData();
|
||||
void _process(const QStringList& paths);
|
||||
|
||||
signals:
|
||||
// Properties
|
||||
@@ -75,6 +82,7 @@ class Manager : public QObject {
|
||||
ProxyModel* m_proxyModel;
|
||||
QHash<QString, Data*> m_dataMap;
|
||||
|
||||
Config::Manager& m_configMgr;
|
||||
Cache::Manager& m_cacheMgr;
|
||||
QSize m_thumbnailSize;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ class Bootstrap {
|
||||
}
|
||||
|
||||
imageMgr = new Image::Manager(
|
||||
*configMgr,
|
||||
*cacheMgr,
|
||||
configMgr->getFocusImageSize());
|
||||
|
||||
@@ -55,7 +56,7 @@ class Bootstrap {
|
||||
void start() {
|
||||
cacheMgr->evictOldEntries();
|
||||
configMgr->captureState();
|
||||
imageMgr->loadAndProcess(configMgr->getWallpapers());
|
||||
imageMgr->loadAndProcess();
|
||||
}
|
||||
|
||||
bool apply(const QString& path) {
|
||||
|
||||
@@ -171,6 +171,10 @@ class Carousel : public QObject {
|
||||
}
|
||||
}
|
||||
|
||||
Q_INVOKABLE void requestReload() {
|
||||
m_imageMgr->loadAndProcess();
|
||||
}
|
||||
|
||||
signals:
|
||||
void currentImageIdChanged();
|
||||
void currentIndexChanged();
|
||||
|
||||
@@ -28,6 +28,7 @@ qt_add_qml_module(${UILIB_NAME}_Modules
|
||||
Modules/ColorControl.qml
|
||||
Modules/TopBar.qml
|
||||
Modules/BottomBar.qml
|
||||
Modules/ReloadButton.qml
|
||||
)
|
||||
qt_add_qml_module(${UILIB_NAME}_Components
|
||||
STATIC
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
ToolButton {
|
||||
id: reloadBtn
|
||||
|
||||
property bool isLoading: false
|
||||
|
||||
icon.name: "view-refresh"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
focusPolicy: Qt.NoFocus
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: 600
|
||||
ToolTip.text: "Reload from disk"
|
||||
enabled: !isLoading
|
||||
}
|
||||
@@ -14,10 +14,12 @@ Item {
|
||||
property alias availableSortTypes: sortCtrl.availableSortTypes
|
||||
property alias selectedSortType: sortCtrl.selectedSortType
|
||||
property alias isSortDescending: sortCtrl.isDescending
|
||||
property alias isLoading: reloadBtn.isLoading
|
||||
|
||||
signal sortTypeSelected(string sortType)
|
||||
signal sortDescendingToggled(bool descending)
|
||||
signal searchDismissed()
|
||||
signal reloadRequested()
|
||||
|
||||
function requestSearchFocus() {
|
||||
searchBar.requestFocus();
|
||||
@@ -63,6 +65,13 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
ReloadButton {
|
||||
id: reloadBtn
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
onClicked: root.reloadRequested()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ Item {
|
||||
root.forceActiveFocus();
|
||||
}
|
||||
|
||||
function onReloadRequested() {
|
||||
CarouselProvider.requestReload();
|
||||
}
|
||||
|
||||
target: topBar
|
||||
}
|
||||
|
||||
@@ -48,6 +52,7 @@ Item {
|
||||
title: carousel.currentImageName
|
||||
availableSortTypes: CarouselProvider.availableSortTypes
|
||||
isSortDescending: CarouselProvider.sortDescending
|
||||
isLoading: CarouselProvider.isLoading
|
||||
onSortTypeSelected: (t) => {
|
||||
return CarouselProvider.setSortType(t);
|
||||
}
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@
|
||||
},
|
||||
"quitOnSelected": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"default": true,
|
||||
"description": "Whether to quit the application after confirming a wallpaper"
|
||||
},
|
||||
"restoreOnClose": {
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ Each item has:
|
||||
`onRestore` (string, default: `""`)
|
||||
: Command executed on restore. Saved state keys are usable as placeholders.
|
||||
|
||||
`quitOnSelected` (boolean, default: `false`)
|
||||
`quitOnSelected` (boolean, default: `true`)
|
||||
: Exit application immediately after confirming a selection.
|
||||
|
||||
`restoreOnClose` (boolean, default: `true`)
|
||||
|
||||
Reference in New Issue
Block a user