5 Commits
Author SHA1 Message Date
Uyanide 64b62246d7 🚀 CD: remove workflow 2026-08-21 18:04:41 +02:00
Uyanide a9f7d9c770 🔧 chore: update email in LICENSE 2026-08-21 17:43:19 +02:00
Uyanide 5d85acecf4 🐛 fix: pick QML controls style explicitly 2026-08-21 17:43:02 +02:00
Uyanide 2dfbd29ed1 💄 style: code style 2026-07-12 19:01:49 +02:00
Uyanide d39e36e096 feat: add reload button to force 'reload from disk'
Release / Build ArchLinux Package (push) Successful in 1m3s
Release / Publish to Gitea Release (push) Successful in 4s
Release / Publish to AUR (push) Successful in 9s
2026-04-05 19:22:12 +02:00
28 changed files with 143 additions and 224 deletions
-162
View File
@@ -1,162 +0,0 @@
name: Release
on:
push:
tags:
- 'v*'
jobs:
build-arch:
name: Build ArchLinux Package
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Extract Version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Generate PKGBUILD
run: |
TAR_URL="https://git.uyani.de/Uyanide/WallReel/archive/v${{ env.VERSION }}.tar.gz"
wget -qO source.tar.gz "$TAR_URL"
SHA256=$(sha256sum source.tar.gz | awk '{print $1}')
cat << 'EOF' > PKGBUILD
# Maintainer: Uyanide <me@uyani.de>
pkgname=wallreel
pkgver=${{ env.VERSION }}
pkgrel=1
pkgdesc="Choose and set desktop wallpapers with customizable themes and actions"
arch=('x86_64')
url="https://git.uyani.de/Uyanide/WallReel"
license=('MIT')
depends=('qt6-base' 'qt6-declarative' 'gcc-libs' 'glibc')
makedepends=('cmake')
options=('!debug')
source=("${pkgname}-${pkgver}.tar.gz::https://git.uyani.de/Uyanide/WallReel/archive/v${pkgver}.tar.gz")
sha256sums=('INSERT_SHA256_HERE')
build() {
cd "wallreel"
cmake -B build -S . \
-DCMAKE_BUILD_TYPE='Release' \
-DCMAKE_INSTALL_PREFIX='/usr' \
-Wno-dev
cmake --build build
}
package() {
cd "wallreel"
DESTDIR="$pkgdir" cmake --install build
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
EOF
sed -i "s/INSERT_SHA256_HERE/$SHA256/" PKGBUILD
- name: Build and Generate AUR Meta
run: |
tar -cf - . | docker run --rm -i archlinux:latest /bin/bash -e -c "
mkdir -p /workspace && cd /workspace
tar -xf -
exec 3>&1 1>&2
pacman-key --init && pacman-key --populate
pacman -Sy --noconfirm archlinux-keyring
pacman -Su --noconfirm base-devel cmake qt6-base qt6-declarative sudo
echo 'MAKEFLAGS="-j$(nproc)"' >> /etc/makepkg.conf
useradd -m builduser
chown -R builduser:builduser /workspace
echo 'builduser ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
su - builduser -c 'cd /workspace && makepkg -sf --noconfirm'
su - builduser -c 'cd /workspace && makepkg --printsrcinfo' > SRCINFO.txt
tar -cf - *.pkg.tar.zst PKGBUILD SRCINFO.txt >&3
" | tar -xf -
- name: Upload Arch Artifacts
uses: actions/upload-artifact@v3
with:
name: arch-artifacts
path: |
*.pkg.tar.zst
PKGBUILD
SRCINFO.txt
publish-gitea:
name: Publish to Gitea Release
needs: [build-arch]
runs-on: ubuntu-latest
steps:
- name: Extract Version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Download Arch Artifacts
uses: actions/download-artifact@v3
with:
name: arch-artifacts
path: .
- name: Publish to Gitea Release
uses: softprops/action-gh-release@v1
with:
name: WallReel ${{ env.VERSION }}
draft: false
prerelease: false
files: "*.pkg.tar.zst"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-aur:
name: Publish to AUR
needs: [build-arch]
runs-on: ubuntu-latest
steps:
- name: Extract Version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Download Arch Artifacts
uses: actions/download-artifact@v3
with:
name: arch-artifacts
path: .
- name: Publish to AUR
env:
AUR_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$AUR_KEY" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
cat <<EOF > ~/.ssh/config
Host aur.archlinux.org
IdentityFile ~/.ssh/aur
User aur
EOF
git config --global user.name "Uyanide"
git config --global user.email "me@uyani.de"
git clone ssh://aur@aur.archlinux.org/wallreel.git aur-repo
cp PKGBUILD aur-repo/
cp SRCINFO.txt aur-repo/.SRCINFO
cd aur-repo
cat << 'EOF' > LICENSE
Copyright (C) 2026 by Uyanide me@uyani.de
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
EOF
git add PKGBUILD LICENSE .SRCINFO
git commit -m "Release v${{ env.VERSION }}"
git push origin master
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) 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(EXECUTABLE_NAME "wallreel")
set(CORELIB_NAME "wallreel-core") set(CORELIB_NAME "wallreel-core")
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2026 Uyanide me@uyani.de Copyright 2026 Uyanide pywang0608@foxmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-2
View File
@@ -1,8 +1,6 @@
#ifndef WALLREEL_CONFIG_DATA_HPP #ifndef WALLREEL_CONFIG_DATA_HPP
#define WALLREEL_CONFIG_DATA_HPP #define WALLREEL_CONFIG_DATA_HPP
#include <qtmetamacros.h>
#include <QColor> #include <QColor>
#include <QHash> #include <QHash>
#include <QList> #include <QList>
+1 -4
View File
@@ -54,9 +54,6 @@ Manager::Manager(
WR_INFO(QString("No search directories specified, using Pictures directory: %1").arg(picturesPath)); WR_INFO(QString("No search directories specified, using Pictures directory: %1").arg(picturesPath));
m_wallpaperConfig.dirs.append({picturesPath, true}); m_wallpaperConfig.dirs.append({picturesPath, true});
} }
WR_DEBUG("Loading wallpapers ...");
_loadWallpapers();
} }
Manager::~Manager() { Manager::~Manager() {
@@ -324,7 +321,7 @@ void Manager::_loadCacheConfig(const QJsonObject& root) {
} }
} }
void Manager::_loadWallpapers() { void Manager::scanWallpapers() {
m_wallpapers.clear(); m_wallpapers.clear();
// Add paths first using a set to avoid duplicates // Add paths first using a set to avoid duplicates
+5 -5
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_CONFIGMGR_HPP #ifndef WALLREEL_CONFIG_MANAGER_HPP
#define WALLREEL_CONFIGMGR_HPP #define WALLREEL_CONFIG_MANAGER_HPP
#include <QDir> #include <QDir>
@@ -72,6 +72,8 @@ class Manager : public QObject {
*/ */
Q_INVOKABLE void captureState(); Q_INVOKABLE void captureState();
void scanWallpapers();
signals: signals:
void stateCaptured(); void stateCaptured();
@@ -83,8 +85,6 @@ class Manager : public QObject {
void _loadActionConfig(const QJsonObject& config); void _loadActionConfig(const QJsonObject& config);
void _loadStyleConfig(const QJsonObject& config); void _loadStyleConfig(const QJsonObject& config);
void _loadCacheConfig(const QJsonObject& config); void _loadCacheConfig(const QJsonObject& config);
// Load wallpapers
void _loadWallpapers();
// Callback for state capture results // Callback for state capture results
void _onCaptureResult(const QString& key, const QString& value); void _onCaptureResult(const QString& key, const QString& value);
@@ -106,4 +106,4 @@ class Manager : public QObject {
} // namespace WallReel::Core::Config } // namespace WallReel::Core::Config
#endif // WALLREEL_CONFIGMGR_HPP #endif // WALLREEL_CONFIG_MANAGER_HPP
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_IMAGEDATA_HPP #ifndef WALLREEL_IMAGE_DATA_HPP
#define WALLREEL_IMAGEDATA_HPP #define WALLREEL_IMAGE_DATA_HPP
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@@ -106,4 +106,4 @@ class Data {
} // namespace WallReel::Core::Image } // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEDATA_HPP #endif // WALLREEL_IMAGE_DATA_HPP
+22
View File
@@ -9,10 +9,12 @@
WALLREEL_DECLARE_SENDER("ImageManager") WALLREEL_DECLARE_SENDER("ImageManager")
WallReel::Core::Image::Manager::Manager( WallReel::Core::Image::Manager::Manager(
Config::Manager& configMgr,
Cache::Manager& cacheMgr, Cache::Manager& cacheMgr,
const QSize& thumbnailSize, const QSize& thumbnailSize,
QObject* parent) QObject* parent)
: QObject(parent), : QObject(parent),
m_configMgr(configMgr),
m_cacheMgr(cacheMgr), m_cacheMgr(cacheMgr),
m_thumbnailSize(thumbnailSize) { m_thumbnailSize(thumbnailSize) {
m_dataModel = new Model(this); m_dataModel = new Model(this);
@@ -38,6 +40,21 @@ WallReel::Core::Image::Manager::~Manager() {
m_watcher.waitForFinished(); 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) { void WallReel::Core::Image::Manager::loadAndProcess(const QStringList& paths) {
if (m_isLoading) { if (m_isLoading) {
WR_WARN("Already loading images. Ignoring new load request."); WR_WARN("Already loading images. Ignoring new load request.");
@@ -48,6 +65,10 @@ void WallReel::Core::Image::Manager::loadAndProcess(const QStringList& paths) {
_clearData(); _clearData();
return _process(paths);
}
void WallReel::Core::Image::Manager::_process(const QStringList& paths) {
m_processedCount = 0; m_processedCount = 0;
m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs); m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs);
// These are all small objects so capturing by value should be fine // 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() { void WallReel::Core::Image::Manager::_clearData() {
m_dataModel->clearData(); m_dataModel->clearData();
m_dataMap.clear();
} }
void WallReel::Core::Image::Manager::_onProgressValueChanged(int value) { void WallReel::Core::Image::Manager::_onProgressValueChanged(int value) {
+11 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_IMAGEMANAGER_HPP #ifndef WALLREEL_IMAGE_MANAGER_HPP
#define WALLREEL_IMAGEMANAGER_HPP #define WALLREEL_IMAGE_MANAGER_HPP
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QDir> #include <QDir>
@@ -8,6 +8,7 @@
#include <atomic> #include <atomic>
#include "Cache/manager.hpp" #include "Cache/manager.hpp"
#include "Config/manager.hpp"
#include "data.hpp" #include "data.hpp"
#include "model.hpp" #include "model.hpp"
@@ -20,6 +21,7 @@ class Manager : public QObject {
// Constructor / Destructor // Constructor / Destructor
Manager( Manager(
Config::Manager& configMgr,
Cache::Manager& cacheMgr, Cache::Manager& cacheMgr,
const QSize& thumbnailSize, const QSize& thumbnailSize,
QObject* parent = nullptr); QObject* parent = nullptr);
@@ -32,6 +34,8 @@ class Manager : public QObject {
int processedCount() const { return m_processedCount.load(std::memory_order_relaxed); } 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(); } int totalCount() const { return m_watcher.progressMaximum(); }
void setSortType(Config::SortType type) { m_proxyModel->setSortType(type); } void setSortType(Config::SortType type) { m_proxyModel->setSortType(type); }
@@ -46,6 +50,8 @@ class Manager : public QObject {
QString searchText() const { return m_proxyModel->getSearchText(); } QString searchText() const { return m_proxyModel->getSearchText(); }
void loadAndProcess();
void loadAndProcess(const QStringList& paths); void loadAndProcess(const QStringList& paths);
void stop(); void stop();
@@ -59,6 +65,7 @@ class Manager : public QObject {
private: private:
void _clearData(); void _clearData();
void _process(const QStringList& paths);
signals: signals:
// Properties // Properties
@@ -75,6 +82,7 @@ class Manager : public QObject {
ProxyModel* m_proxyModel; ProxyModel* m_proxyModel;
QHash<QString, Data*> m_dataMap; QHash<QString, Data*> m_dataMap;
Config::Manager& m_configMgr;
Cache::Manager& m_cacheMgr; Cache::Manager& m_cacheMgr;
QSize m_thumbnailSize; QSize m_thumbnailSize;
@@ -88,4 +96,4 @@ class Manager : public QObject {
} // namespace WallReel::Core::Image } // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEMANAGER_HPP #endif // WALLREEL_IMAGE_MANAGER_HPP
+5 -5
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_IMAGEMODEL_HPP #ifndef WALLREEL_IMAGE_MODEL_HPP
#define WALLREEL_IMAGEMODEL_HPP #define WALLREEL_IMAGE_MODEL_HPP
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
@@ -78,10 +78,10 @@ class ProxyModel : public QSortFilterProxyModel {
private: private:
QString m_searchText; QString m_searchText;
Config::SortType m_sortType; Config::SortType m_sortType = Config::SortType::Date;
bool m_sortDescending; bool m_sortDescending = true;
}; };
} // namespace WallReel::Core::Image } // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEMODEL_HPP #endif // WALLREEL_IMAGE_MODEL_HPP
-2
View File
@@ -1,8 +1,6 @@
#ifndef WALLREEL_PALETTE_DATA_HPP #ifndef WALLREEL_PALETTE_DATA_HPP
#define WALLREEL_PALETTE_DATA_HPP #define WALLREEL_PALETTE_DATA_HPP
#include <qcolor.h>
#include <QColor> #include <QColor>
#include <QList> #include <QList>
#include <QObject> #include <QObject>
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_CORE_PALETTE_DOMCOLOR_HPP #ifndef WALLREEL_PALETTE_DOMCOLOR_HPP
#define WALLREEL_CORE_PALETTE_DOMCOLOR_HPP #define WALLREEL_PALETTE_DOMCOLOR_HPP
#include <QImage> #include <QImage>
@@ -15,4 +15,4 @@ QColor getDominantColor(const QImage& image);
} // namespace WallReel::Core::Palette } // namespace WallReel::Core::Palette
#endif // WALLREEL_CORE_PALETTE_DOMCOLOR_HPP #endif // WALLREEL_PALETTE_DOMCOLOR_HPP
-2
View File
@@ -1,7 +1,5 @@
#include "manager.hpp" #include "manager.hpp"
#include <qcontainerfwd.h>
#include "Palette/matchcolor.hpp" #include "Palette/matchcolor.hpp"
#include "Utils/misc.hpp" #include "Utils/misc.hpp"
#include "logger.hpp" #include "logger.hpp"
-2
View File
@@ -1,8 +1,6 @@
#ifndef WALLREEL_PALETTE_MANAGER_HPP #ifndef WALLREEL_PALETTE_MANAGER_HPP
#define WALLREEL_PALETTE_MANAGER_HPP #define WALLREEL_PALETTE_MANAGER_HPP
#include <qcolor.h>
#include "Config/data.hpp" #include "Config/data.hpp"
#include "Image/manager.hpp" #include "Image/manager.hpp"
#include "data.hpp" #include "data.hpp"
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_CORE_PALETTE_MATCHCOLOR_HPP #ifndef WALLREEL_PALETTE_MATCHCOLOR_HPP
#define WALLREEL_CORE_PALETTE_MATCHCOLOR_HPP #define WALLREEL_PALETTE_MATCHCOLOR_HPP
#include "data.hpp" #include "data.hpp"
@@ -16,4 +16,4 @@ ColorItem bestMatch(const QColor& target, const QList<ColorItem>& candidates);
} // namespace WallReel::Core::Palette } // namespace WallReel::Core::Palette
#endif // WALLREEL_CORE_PALETTE_MATCHCOLOR_HPP #endif // WALLREEL_PALETTE_MATCHCOLOR_HPP
+2 -1
View File
@@ -36,6 +36,7 @@ class Bootstrap {
} }
imageMgr = new Image::Manager( imageMgr = new Image::Manager(
*configMgr,
*cacheMgr, *cacheMgr,
configMgr->getFocusImageSize()); configMgr->getFocusImageSize());
@@ -55,7 +56,7 @@ class Bootstrap {
void start() { void start() {
cacheMgr->evictOldEntries(); cacheMgr->evictOldEntries();
configMgr->captureState(); configMgr->captureState();
imageMgr->loadAndProcess(configMgr->getWallpapers()); imageMgr->loadAndProcess();
} }
bool apply(const QString& path) { bool apply(const QString& path) {
+4
View File
@@ -171,6 +171,10 @@ class Carousel : public QObject {
} }
} }
Q_INVOKABLE void requestReload() {
m_imageMgr->loadAndProcess();
}
signals: signals:
void currentImageIdChanged(); void currentImageIdChanged();
void currentIndexChanged(); void currentIndexChanged();
-4
View File
@@ -1,9 +1,5 @@
#include "Service/wallpaper.hpp" #include "Service/wallpaper.hpp"
#include <qprocess.h>
#include <QColor>
#include "logger.hpp" #include "logger.hpp"
WALLREEL_DECLARE_SENDER("WallpaperService") WALLREEL_DECLARE_SENDER("WallpaperService")
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_WALLPAPERSERVICE_HPP #ifndef WALLREEL_SERVICE_WALLPAPER_HPP
#define WALLREEL_WALLPAPERSERVICE_HPP #define WALLREEL_SERVICE_WALLPAPER_HPP
#include <QProcess> #include <QProcess>
#include <QTimer> #include <QTimer>
@@ -38,4 +38,4 @@ class WallpaperService : public QObject {
} // namespace WallReel::Core::Service } // namespace WallReel::Core::Service
#endif // WALLREEL_WALLPAPERSERVICE_HPP #endif // WALLREEL_SERVICE_WALLPAPER_HPP
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef WALLREEL_MISC_HPP #ifndef WALLREEL_UTILS_MISC_HPP
#define WALLREEL_MISC_HPP #define WALLREEL_UTILS_MISC_HPP
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@@ -199,4 +199,4 @@ inline void printPath(const QString& path, std::FILE* out = stdout) {
} // namespace WallReel::Core::Utils } // namespace WallReel::Core::Utils
#endif // WALLREEL_MISC_HPP #endif // WALLREEL_UTILS_MISC_HPP
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef TEXTTEMPLATE_HPP #ifndef WALLREEL_UTILS_TEXTTEMPLATE_HPP
#define TEXTTEMPLATE_HPP #define WALLREEL_UTILS_TEXTTEMPLATE_HPP
#include <QMap> #include <QMap>
#include <QRegularExpression> #include <QRegularExpression>
@@ -139,4 +139,4 @@ inline QStringList extractTemplateKeys(const QString& templateStr) {
} // namespace WallReel::Core::Utils } // namespace WallReel::Core::Utils
#endif // TEXTTEMPLATE_HPP #endif // WALLREEL_UTILS_TEXTTEMPLATE_HPP
+4 -1
View File
@@ -1,4 +1,5 @@
#pragma once #ifndef WALLREEL_CORE_APPOPTIONS_HPP
#define WALLREEL_CORE_APPOPTIONS_HPP
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QStringList> #include <QStringList>
@@ -36,3 +37,5 @@ class AppOptions {
}; };
} // namespace WallReel::Core } // namespace WallReel::Core
#endif // WALLREEL_CORE_APPOPTIONS_HPP
-2
View File
@@ -1,8 +1,6 @@
#ifndef WALLREEL_LOGGER_HPP #ifndef WALLREEL_LOGGER_HPP
#define WALLREEL_LOGGER_HPP #define WALLREEL_LOGGER_HPP
#include <qcontainerfwd.h>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QString> #include <QString>
#include <cstdio> #include <cstdio>
+1
View File
@@ -28,6 +28,7 @@ qt_add_qml_module(${UILIB_NAME}_Modules
Modules/ColorControl.qml Modules/ColorControl.qml
Modules/TopBar.qml Modules/TopBar.qml
Modules/BottomBar.qml Modules/BottomBar.qml
Modules/ReloadButton.qml
) )
qt_add_qml_module(${UILIB_NAME}_Components qt_add_qml_module(${UILIB_NAME}_Components
STATIC STATIC
+17
View File
@@ -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
}
+9
View File
@@ -14,10 +14,12 @@ Item {
property alias availableSortTypes: sortCtrl.availableSortTypes property alias availableSortTypes: sortCtrl.availableSortTypes
property alias selectedSortType: sortCtrl.selectedSortType property alias selectedSortType: sortCtrl.selectedSortType
property alias isSortDescending: sortCtrl.isDescending property alias isSortDescending: sortCtrl.isDescending
property alias isLoading: reloadBtn.isLoading
signal sortTypeSelected(string sortType) signal sortTypeSelected(string sortType)
signal sortDescendingToggled(bool descending) signal sortDescendingToggled(bool descending)
signal searchDismissed() signal searchDismissed()
signal reloadRequested()
function requestSearchFocus() { function requestSearchFocus() {
searchBar.requestFocus(); searchBar.requestFocus();
@@ -63,6 +65,13 @@ Item {
} }
} }
ReloadButton {
id: reloadBtn
Layout.alignment: Qt.AlignVCenter
onClicked: root.reloadRequested()
}
} }
} }
+5
View File
@@ -32,6 +32,10 @@ Item {
root.forceActiveFocus(); root.forceActiveFocus();
} }
function onReloadRequested() {
CarouselProvider.requestReload();
}
target: topBar target: topBar
} }
@@ -48,6 +52,7 @@ Item {
title: carousel.currentImageName title: carousel.currentImageName
availableSortTypes: CarouselProvider.availableSortTypes availableSortTypes: CarouselProvider.availableSortTypes
isSortDescending: CarouselProvider.sortDescending isSortDescending: CarouselProvider.sortDescending
isLoading: CarouselProvider.isLoading
onSortTypeSelected: (t) => { onSortTypeSelected: (t) => {
return CarouselProvider.setSortType(t); return CarouselProvider.setSortType(t);
} }
+37 -9
View File
@@ -1,8 +1,8 @@
#include <qobject.h>
#include <QApplication> #include <QApplication>
#include <QFileInfo>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext> #include <QQmlContext>
#include <QQuickStyle>
#include <QSocketNotifier> #include <QSocketNotifier>
extern "C" { extern "C" {
@@ -21,6 +21,26 @@ using namespace WallReel::Core;
WALLREEL_DECLARE_SENDER("Main") WALLREEL_DECLARE_SENDER("Main")
static QString pickControlsStyle(const QQmlApplicationEngine& engine) {
// Respect env
if (!qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE"))
return {};
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
using namespace Qt::StringLiterals;
// Prefer KDE style if available,
for (const QString& p : engine.importPathList())
if (QFileInfo::exists(p + u"/org/kde/desktop/qmldir"_s))
return u"org.kde.desktop"_s;
// fallback to Fusion
return u"Fusion"_s;
#else
for (const QString& p : engine.importPathList())
if (QFileInfo::exists(p + u"/org/kde/desktop/qmldir"_qs))
return u"org.kde.desktop"_qs;
return u"Fusion"_qs;
#endif
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// Destruction order after QApplication quits its event loop: // Destruction order after QApplication quits its event loop:
// 1. QQmlApplicationEngine (with all QML objects) // 1. QQmlApplicationEngine (with all QML objects)
@@ -46,12 +66,14 @@ int main(int argc, char* argv[]) {
QApplication a(argc, argv); QApplication a(argc, argv);
a.setApplicationName(APP_NAME); a.setApplicationName(APP_NAME);
a.setApplicationVersion(APP_VERSION); a.setApplicationVersion(APP_VERSION);
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
a.setWindowIcon(QIcon(u":/icon.svg"_s)); a.setWindowIcon(QIcon(u":/icon.svg"_s));
#else #else
a.setWindowIcon(QIcon(u":/%1.svg"_qs.arg(APP_NAME))); a.setWindowIcon(QIcon(u":/icon.svg"_qs));
#endif #endif
}
{ {
Logger::init(); Logger::init();
@@ -105,6 +127,10 @@ int main(int argc, char* argv[]) {
{ {
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
if (const QString s = pickControlsStyle(engine); !s.isEmpty()) {
QQuickStyle::setStyle(s);
}
QObject::connect( QObject::connect(
&engine, &engine,
&QQmlApplicationEngine::objectCreationFailed, &QQmlApplicationEngine::objectCreationFailed,
@@ -112,13 +138,15 @@ int main(int argc, char* argv[]) {
[]() { QCoreApplication::exit(-1); }, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection); Qt::QueuedConnection);
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
engine.loadFromModule(UIMODULE_URI, u"Main"_s); engine.loadFromModule(UIMODULE_URI, u"Main"_s);
#else #else
engine.addImportPath(u"qrc:/"_qs); engine.addImportPath(u"qrc:/"_qs);
engine.load(QUrl(u"qrc:/WallReel/UI/Main.qml"_qs)); engine.load(QUrl(u"qrc:/WallReel/UI/Main.qml"_qs));
#endif #endif
}
bootstrap.start(); bootstrap.start();