init
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
.cache
|
||||||
|
.vscode
|
||||||
|
build
|
||||||
|
*.log
|
||||||
|
|
||||||
|
*.user
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(wallpaper_chooser VERSION 0.1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||||
|
|
||||||
|
set(PROJECT_SOURCES
|
||||||
|
main.cpp
|
||||||
|
mainwindow.cpp
|
||||||
|
mainwindow.h
|
||||||
|
mainwindow.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
qt_add_executable(wallpaper_chooser
|
||||||
|
MANUAL_FINALIZATION
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
images_carousel.h images_carousel.cpp images_carousel.ui
|
||||||
|
config.h config.cpp
|
||||||
|
logger.h
|
||||||
|
)
|
||||||
|
# Define target properties for Android with Qt 6 as:
|
||||||
|
# set_property(TARGET wallpaper_chooser APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||||
|
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||||
|
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||||
|
else()
|
||||||
|
if(ANDROID)
|
||||||
|
add_library(wallpaper_chooser SHARED
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||||
|
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||||
|
else()
|
||||||
|
add_executable(wallpaper_chooser
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(wallpaper_chooser PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||||
|
|
||||||
|
target_include_directories(wallpaper_chooser PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||||
|
# If you are developing for iOS or macOS you should consider setting an
|
||||||
|
# explicit, fixed bundle identifier manually though.
|
||||||
|
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||||
|
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.wallpaper_chooser)
|
||||||
|
endif()
|
||||||
|
set_target_properties(wallpaper_chooser PROPERTIES
|
||||||
|
${BUNDLE_ID_OPTION}
|
||||||
|
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||||
|
MACOSX_BUNDLE TRUE
|
||||||
|
WIN32_EXECUTABLE TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS wallpaper_chooser
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt_finalize_executable(wallpaper_chooser)
|
||||||
|
endif()
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 01:34:52
|
||||||
|
* @LastEditTime: 2025-08-05 12:17:37
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QProcessEnvironment>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
using namespace GeneralLogger;
|
||||||
|
|
||||||
|
static QString expandPath(const QString &path);
|
||||||
|
|
||||||
|
const QString Config::s_DefaultConfigFileName = "config.json";
|
||||||
|
|
||||||
|
Config::Config(const QString &configDir, const QStringList &searchDirs, QObject *parent) : QObject(parent) {
|
||||||
|
info(QString("Loading configuration from: %1").arg(configDir));
|
||||||
|
_loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName);
|
||||||
|
|
||||||
|
info(QString("Additional search directories: %1").arg(searchDirs.join(", ")));
|
||||||
|
m_configItems.wallpaperDirs.append(searchDirs);
|
||||||
|
|
||||||
|
info("Loading wallpapers ...");
|
||||||
|
_loadWallpapers();
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::~Config() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::_loadConfig(const QString &configPath) {
|
||||||
|
QFile configFile(configPath);
|
||||||
|
if (!configFile.open(QIODevice::ReadOnly)) {
|
||||||
|
error(QString("Failed to open config file: %1").arg(configPath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray configData = configFile.readAll();
|
||||||
|
configFile.close();
|
||||||
|
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(configData);
|
||||||
|
if (jsonDoc.isNull() || !jsonDoc.isObject()) {
|
||||||
|
error(QString("Invalid JSON format in config file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const auto parseJsonArray = [](const QJsonObject &obj, const QString &key, QStringList &list) {
|
||||||
|
if (obj.contains(key) && obj[key].isArray()) {
|
||||||
|
QJsonArray array = obj[key].toArray();
|
||||||
|
for (const QJsonValue &value : array) {
|
||||||
|
if (value.isString()) {
|
||||||
|
list.append(::expandPath(value.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn(QString("Key '%1' not found or not an array in config").arg(key));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto jsonObj = jsonDoc.object();
|
||||||
|
if (!jsonObj.contains("wallpaper") || !jsonObj["wallpaper"].isObject()) {
|
||||||
|
warn("Key 'wallpaper' not fount or not an object in config");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto wallpaperObj = jsonObj.value("wallpaper").toObject();
|
||||||
|
parseJsonArray(wallpaperObj, "paths", m_configItems.wallpaperPaths);
|
||||||
|
parseJsonArray(wallpaperObj, "dirs", m_configItems.wallpaperDirs);
|
||||||
|
parseJsonArray(wallpaperObj, "excludes", m_configItems.wallpaperExcludes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::_loadWallpapers() {
|
||||||
|
m_wallpapers.clear();
|
||||||
|
|
||||||
|
QSet<QString> paths;
|
||||||
|
|
||||||
|
info(QString("Loading wallpapers from %1 specified paths").arg(m_configItems.wallpaperPaths.size()), LogIndent::STEP);
|
||||||
|
for (const QString &path : m_configItems.wallpaperPaths) {
|
||||||
|
paths.insert(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
info(QString("Loading wallpapers from %1 specified directories").arg(m_configItems.wallpaperDirs.size()), LogIndent::STEP);
|
||||||
|
for (const QString &dirPath : m_configItems.wallpaperDirs) {
|
||||||
|
QDir dir(dirPath);
|
||||||
|
if (dir.exists()) {
|
||||||
|
QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||||
|
for (const QString &file : files) {
|
||||||
|
QString filePath = dir.filePath(file);
|
||||||
|
paths.insert(filePath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn(QString("Directory '%1' does not exist").arg(dirPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info(QString("Excluding %1 specified paths").arg(m_configItems.wallpaperExcludes.size()), LogIndent::STEP);
|
||||||
|
for (const QString &exclude : m_configItems.wallpaperExcludes) {
|
||||||
|
paths.remove(exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_wallpapers.reserve(paths.size());
|
||||||
|
for (const QString &path : paths) {
|
||||||
|
if (isValidImageFile(path)) {
|
||||||
|
m_wallpapers.append(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info(QString("Found %1 wallpapers").arg(paths.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Config::isValidImageFile(const QString &filePath) {
|
||||||
|
static const QStringList validExtensions = {
|
||||||
|
".jpg",
|
||||||
|
".jpeg",
|
||||||
|
".png",
|
||||||
|
".bmp",
|
||||||
|
".gif",
|
||||||
|
".webp",
|
||||||
|
".tiff",
|
||||||
|
".avif",
|
||||||
|
".heic",
|
||||||
|
".heif"};
|
||||||
|
|
||||||
|
// check if exist
|
||||||
|
if (!QFile::exists(filePath)) {
|
||||||
|
warn(QString("File does not exist: %1").arg(filePath));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// check if normal file
|
||||||
|
QFileInfo fileInfo(filePath);
|
||||||
|
if (!fileInfo.isFile() || !fileInfo.isReadable()) {
|
||||||
|
warn(QString("Invalid file: %1").arg(filePath));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// check if valid extension
|
||||||
|
for (const QString &ext : validExtensions) {
|
||||||
|
if (filePath.endsWith(ext, Qt::CaseInsensitive)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warn(QString("Unsupported file type: %1").arg(filePath));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString expandPath(const QString &path) {
|
||||||
|
QString expandedPath = path;
|
||||||
|
|
||||||
|
if (expandedPath.startsWith("~/")) {
|
||||||
|
expandedPath.replace(0, 1, QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
|
||||||
|
} else if (expandedPath == "~") {
|
||||||
|
expandedPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
QRegularExpression envVarRegex(R"(\$([A-Za-z_][A-Za-z0-9_]*))");
|
||||||
|
QRegularExpressionMatchIterator i = envVarRegex.globalMatch(expandedPath);
|
||||||
|
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QRegularExpressionMatch match = i.next();
|
||||||
|
QString varName = match.captured(1);
|
||||||
|
QString varValue = env.value(varName);
|
||||||
|
if (!varValue.isEmpty()) {
|
||||||
|
expandedPath.replace(match.captured(0), varValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QDir::cleanPath(expandedPath);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 01:34:52
|
||||||
|
* @LastEditTime: 2025-08-05 12:14:04
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class Config : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Config(const QString& configDir, const QStringList& searchDirs = {}, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
~Config();
|
||||||
|
|
||||||
|
static bool isValidImageFile(const QString& filePath);
|
||||||
|
|
||||||
|
[[nodiscard]] const QStringList& getWallpapers() const { return m_wallpapers; }
|
||||||
|
|
||||||
|
[[nodiscard]] qint64 getWallpaperCount() const { return m_wallpapers.size(); }
|
||||||
|
|
||||||
|
static const QString s_DefaultConfigFileName;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
_loadConfig(const QString& configPath);
|
||||||
|
void _loadWallpapers();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ConfigItems {
|
||||||
|
QStringList wallpaperPaths;
|
||||||
|
QStringList wallpaperDirs;
|
||||||
|
QStringList wallpaperExcludes;
|
||||||
|
} m_configItems;
|
||||||
|
|
||||||
|
QStringList m_wallpapers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_H
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "images_carousel.h"
|
||||||
|
|
||||||
|
#include "ui_images_carousel.h"
|
||||||
|
|
||||||
|
ImagesCarousel::ImagesCarousel(QWidget *parent) : QWidget(parent),
|
||||||
|
ui(new Ui::ImagesCarousel) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImagesCarousel::~ImagesCarousel() {
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef IMAGES_CAROUSEL_H
|
||||||
|
#define IMAGES_CAROUSEL_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ImagesCarousel;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImagesCarousel : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ImagesCarousel(QWidget *parent = nullptr);
|
||||||
|
~ImagesCarousel();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ImagesCarousel *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMAGES_CAROUSEL_H
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ImagesCarousel</class>
|
||||||
|
<widget class="QWidget" name="ImagesCarousel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 10:43:31
|
||||||
|
* @LastEditTime: 2025-08-05 11:49:27
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#ifndef GENERAL_LOGGER_H
|
||||||
|
#define GENERAL_LOGGER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
namespace GeneralLogger {
|
||||||
|
|
||||||
|
inline constexpr const char* colorInfoMsg[]{"\033[32m", "\033[0m", "\033[0m"};
|
||||||
|
|
||||||
|
enum LogIndent : qint32 {
|
||||||
|
GENERAL = 0,
|
||||||
|
STEP = 1,
|
||||||
|
DETAIL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef GENERAL_LOGGER_DISABLED
|
||||||
|
#define ENSURE_ENABLED return;
|
||||||
|
#else
|
||||||
|
#define ENSURE_ENABLED
|
||||||
|
extern QTextStream g_logStream;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void
|
||||||
|
info(const QString& msg,
|
||||||
|
const LogIndent indent = GENERAL,
|
||||||
|
const bool color = true) {
|
||||||
|
ENSURE_ENABLED
|
||||||
|
|
||||||
|
g_logStream << (color ? "\033[92m" : "") << "[INFO] ";
|
||||||
|
for (qint32 i = 0; i < indent; i++) g_logStream << " ";
|
||||||
|
g_logStream << (color ? colorInfoMsg[indent] : "") << msg << (color ? "\033[0m\n" : "\n");
|
||||||
|
g_logStream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
warn(const QString& msg,
|
||||||
|
const LogIndent indent = GENERAL,
|
||||||
|
const bool color = true) {
|
||||||
|
ENSURE_ENABLED
|
||||||
|
|
||||||
|
g_logStream << (color ? "\033[93m" : "") << "[WARN] ";
|
||||||
|
for (uint32_t i = 0; i < indent; i++) g_logStream << " ";
|
||||||
|
g_logStream << (color ? "\033[33m" : "") << msg << (color ? "\033[0m\n" : "\n");
|
||||||
|
g_logStream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
error(const QString& msg,
|
||||||
|
const LogIndent indent = GENERAL,
|
||||||
|
const bool color = true) {
|
||||||
|
ENSURE_ENABLED
|
||||||
|
|
||||||
|
g_logStream << (color ? "\033[91m" : "") << "[ERROR] ";
|
||||||
|
for (uint32_t i = 0; i < indent; i++) g_logStream << " ";
|
||||||
|
g_logStream << (color ? "\033[31m" : "") << msg << (color ? "\033[0m\n" : "\n");
|
||||||
|
g_logStream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ENSURE_ENABLED
|
||||||
|
|
||||||
|
}; // namespace GeneralLogger
|
||||||
|
|
||||||
|
#endif // GENERAL_LOGGER_H
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 00:37:58
|
||||||
|
* @LastEditTime: 2025-08-05 12:16:35
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#include <qapplication.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
QTextStream GeneralLogger::g_logStream(stderr);
|
||||||
|
|
||||||
|
static QString getConfigDir() {
|
||||||
|
auto configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||||
|
if (configDir.isEmpty()) {
|
||||||
|
configDir = QDir::homePath() + QDir::separator() + ".config" + QDir::separator() + "wallpaper_chooser";
|
||||||
|
}
|
||||||
|
QDir().mkpath(configDir);
|
||||||
|
return configDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
MainWindow w(::getConfigDir());
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 00:37:58
|
||||||
|
* @LastEditTime: 2025-08-05 12:18:00
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#include "./ui_mainwindow.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(const QString &configDir, QWidget *parent)
|
||||||
|
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
|
|
||||||
|
m_config = new Config(configDir, {}, this);
|
||||||
|
|
||||||
|
ui->setupUi(this);
|
||||||
|
_setupUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow() {
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::_setupUI() {
|
||||||
|
connect(ui->confirmButton, &QPushButton::clicked, this, &MainWindow::onConfirm);
|
||||||
|
connect(ui->cancelButton, &QPushButton::clicked, this, &MainWindow::onCancel);
|
||||||
|
ui->confirmButton->setFocusPolicy(Qt::NoFocus);
|
||||||
|
ui->cancelButton->setFocusPolicy(Qt::NoFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::keyPressEvent(QKeyEvent *event) {
|
||||||
|
if (event->key() == Qt::Key_Escape) {
|
||||||
|
onCancel();
|
||||||
|
} else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
|
||||||
|
onConfirm();
|
||||||
|
} else {
|
||||||
|
QMainWindow::keyPressEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onConfirm() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onCancel() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* @Author: Uyanide pywang0608@foxmail.com
|
||||||
|
* @Date: 2025-08-05 00:37:58
|
||||||
|
* @LastEditTime: 2025-08-05 12:01:25
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow(const QString &configDir, QWidget *parent = nullptr);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onConfirm();
|
||||||
|
void onCancel();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _setupUI();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
Config *m_config;
|
||||||
|
};
|
||||||
|
#endif // MAINWINDOW_H
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>750</width>
|
||||||
|
<height>500</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>750</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>750</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<property name="dockOptions">
|
||||||
|
<set>QMainWindow::DockOption::AllowTabbedDocks|QMainWindow::DockOption::AnimatedDocks</set>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="ImagesCarousel" name="carousel" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="actions" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="cancelButton">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: #f38ba8</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="confirmButton">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: #a6e3a1</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Confirm</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>ImagesCarousel</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>images_carousel.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Reference in New Issue
Block a user