diff --git a/README.md b/README.md index cb8d96c..9238305 100644 --- a/README.md +++ b/README.md @@ -91,16 +91,13 @@ make Once the build process is finished, this should create a new `output` folder containing the app and all the required support files to run. -## 5.5. Running linux-wallpaperengine +## 2.1. Running linux-wallpaperengine Now you can run the program using the following command: ``` ./linux-wallpaperengine ``` -## 5.6 Selecting a wallpaper -In the graphical user interface (GUI), start by selecting the desired screen. Then simply click on a wallpaper to display it. - #### Wayland Has only been tested under wlroots but should work on any flavour as long as wlr-layer-shell-unstable is supported. @@ -109,29 +106,6 @@ Only screens configured with the XRandr extension are supported. **IMPORTANT: Right now this doesn't work if there is anything drawing to the background (like a compositor, gnome, kde, nautilus, etc)** -### 5.6.1 Using custom-flags -To further customize your wallpaper (e.g., adjusting the volume), you can enter one or more of the following flags in the text field at the bottom of the GUI **before** selecting a wallpaper: - -| Option | Description | -|--------|-------------| -| `--silent` | Mute background audio | -| `--volume ` | Set audio volume | -| `--noautomute` | Don't mute when other apps play audio | -| `--no-audio-processing` | Disable audio reactive features | -| `--fps ` | Limit frame rate | -| `--scaling ` | Wallpaper scaling: `stretch`, `fit`, `fill`, or `default` | -| `--clamping ` | Set texture clamping: `clamp`, `border`, `repeat` | -| `--disable-mouse` | Disable mouse interaction | -| `--disable-parallax` | Disable parallax effect on backgrounds that support it | -| `--no-fullscreen-pause` | Prevent pausing while fullscreen apps are running | - -## ๐Ÿงช Wayland & X11 Support - -- **Wayland**: Works with compositors that support `wlr-layer-shell-unstable`. -- **X11**: Requires XRandr. Use `--screen-root ` (as shown in `xrandr`). - -> โš  For X11 users: Currently doesn't work if a compositor or desktop environment (e.g. GNOME, KDE, Nautilus) is drawing the background. - --- ## ๐ŸŒˆ Example Backgrounds diff --git a/src/Qt/UIWindow.cpp b/src/Qt/UIWindow.cpp index 2ecfe5d..4c7c7b7 100644 --- a/src/Qt/UIWindow.cpp +++ b/src/Qt/UIWindow.cpp @@ -1,9 +1,11 @@ #include "UIWindow.h" #include "Qt/SingleInstanceManager.h" +#include #include "Qt/WallpaperButton.h" #include #include #include +#include #include #include #include @@ -40,7 +42,6 @@ UIWindow::UIWindow(QWidget* parent, QApplication* qapp, SingleInstanceManager* ig) { this->qapp = qapp; this->screenSelector = new QComboBox(this); - this->extraFlagsInput = new QLineEdit(this); this->wallpaperEngine = new QProcess(this); this->instanceGuard = ig; this->buttonLayout = new QGridLayout(this); @@ -49,17 +50,19 @@ UIWindow::UIWindow(QWidget* parent, QApplication* qapp, SingleInstanceManager* i } void UIWindow::setupUIWindow(std::vector wallpaperPaths) { - this->setWindowTitle("Wallpapers :3"); + this->setWindowTitle("Linux-WallpaperEngine"); + + this->setStyleSheet(R"( + QWidget { + background-color: #2B2A33; + color: white; + } + )"); + + this->setAttribute(Qt::WA_StyledBackground, true); - // palette - auto* pal = new QPalette(); - pal->setColor(QPalette::Window, QColor(0x2B, 0x2A, 0x33, 0xFF)); - this->setAutoFillBackground(true); - this->setPalette(*pal); - auto* scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); - scrollArea->setPalette(*pal); auto* container = new QWidget(); @@ -73,22 +76,21 @@ void UIWindow::setupUIWindow(std::vector wallpaperPaths) { button->setEnabled(false); this->selectedWallpapers[this->screenSelector->currentText().toStdString()] = clickedPath.toStdString(); - this->extraFlags[this->screenSelector->currentText().toStdString()] = split(this->extraFlagsInput->text().toStdString(), ' '); - - startNewWallpaperEngine(); - - QObject::connect(wallpaperEngine, &QProcess::started, button, [this, button]() { - button->setEnabled(true); - updateSelectedButton(); - this->wallpaperSettingsWidget->update(this->selectedWallpapers[this->screenSelector->currentText().toStdString()]); - }); + + // startNewWallpaperEngine(); + // Doesn't need to start a new WallpaperEngine here since update wallpaperSettings does emit applySettings() + updateSelectedButton(); + this->wallpaperSettingsWidget->update(this->selectedWallpapers[this->screenSelector->currentText().toStdString()]); }); - int row = i / cols; int col = i % cols; buttonLayout->addWidget(button, row, col); } + QObject::connect(wallpaperEngine, &QProcess::started, this, [this]() { + updateSelectedButton(); + }); + QObject::connect(this->qapp, &QCoreApplication::aboutToQuit, this, [this]() { wallpaperEngine->terminate(); wallpaperEngine->waitForFinished(3000); @@ -114,20 +116,24 @@ void UIWindow::setupUIWindow(std::vector wallpaperPaths) { this->screenSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); this->screenSelector->setFixedHeight(48); - auto font = screenSelector->font(); - font.setPointSize(18); - this->screenSelector->setFont(font); + this->screenSelector->setView(new QListView()); + this->screenSelector->view()->setStyleSheet( + "QListView { background-color:#2B2A33; selection-background-color:#4488FF; color:white; }" + "QListView::item:hover { background-color:#4488FF; }" + ); + + this->screenSelector->setStyleSheet( + "font-size: 24px;" + ); - this->screenSelector->setPalette(*pal); QObject::connect(this->screenSelector, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { updateSelectedButton(); this->wallpaperSettingsWidget->update(this->selectedWallpapers[this->screenSelector->currentText().toStdString()]); }); - auto* screenSelectorLayout = new QVBoxLayout(); + auto* screenSelectorLayout = new QVBoxLayout(this); auto* label = new QLabel("Screen Selector:"); - label->setFont(font); screenSelectorLayout->addWidget(label); screenSelectorLayout->addWidget(screenSelector); @@ -155,12 +161,16 @@ void UIWindow::setupUIWindow(std::vector wallpaperPaths) { // right side this->wallpaperSettingsWidget = new WallpaperSettingsWidget(splitWidget); + + connect(this->wallpaperSettingsWidget, &WallpaperSettingsWidget::applySettings, this, [this](const std::string& flags) { + this->extraFlags[this->screenSelector->currentText().toStdString()] = split(flags, ' '); + startNewWallpaperEngine(); + }); splitLayout->addWidget(leftWidget, 2); splitLayout->addWidget(this->wallpaperSettingsWidget, 1); mainlayout->addWidget(splitWidget); - mainlayout->addWidget(extraFlagsInput); this->setLayout(mainlayout); // update Buttons @@ -209,6 +219,7 @@ void UIWindow::startNewWallpaperEngine() { wallpaperEngine->waitForFinished(); } } + // delete this->wallpaperEngine; // create args QStringList args; @@ -239,6 +250,8 @@ void UIWindow::updateSelectedButton() { auto* button = dynamic_cast(widget); if (!button) continue; + button->setEnabled(true); + std::string selected = this->selectedWallpapers[this->screenSelector->currentText().toStdString()]; QString currentStyle = button->styleSheet(); QString newStyle = currentStyle; diff --git a/src/Qt/UIWindow.h b/src/Qt/UIWindow.h index 57a242a..19037be 100644 --- a/src/Qt/UIWindow.h +++ b/src/Qt/UIWindow.h @@ -1,7 +1,10 @@ #pragma once #include "Qt/SingleInstanceManager.h" +#include +#include #include +#include #include #include #include @@ -30,7 +33,6 @@ #include #include #include -#include #include "Qt/WallpaperSettingsWidget.h" class UIWindow : public QWidget { @@ -45,7 +47,6 @@ class UIWindow : public QWidget { QApplication* qapp; SingleInstanceManager* instanceGuard; QComboBox* screenSelector; - QLineEdit* extraFlagsInput; QGridLayout* buttonLayout; WallpaperSettingsWidget* wallpaperSettingsWidget; diff --git a/src/Qt/WallpaperButton.cpp b/src/Qt/WallpaperButton.cpp index 44426d4..a11a0bf 100644 --- a/src/Qt/WallpaperButton.cpp +++ b/src/Qt/WallpaperButton.cpp @@ -61,5 +61,4 @@ void WallpaperButton::resizeEvent(QResizeEvent* event) { QToolButton::resizeEvent(event); int size = std::min(event->size().width(), event->size().height()) * 0.8f; setIconSize(QSize(size, size)); - } diff --git a/src/Qt/WallpaperSettingsWidget.cpp b/src/Qt/WallpaperSettingsWidget.cpp index c68317e..8d5670c 100644 --- a/src/Qt/WallpaperSettingsWidget.cpp +++ b/src/Qt/WallpaperSettingsWidget.cpp @@ -1,21 +1,59 @@ #include "WallpaperSettingsWidget.h" #include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include "WallpaperEngine/Assets/CCombinedContainer.h" +#include "WallpaperEngine/Logging/CLog.h" WallpaperSettingsWidget::WallpaperSettingsWidget(QWidget* parent) : QWidget(parent) { + layout->setSpacing(5); preview.title = new QLabel("...", this); preview.title->setAlignment(Qt::AlignTop); + preview.title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); preview.image = new QLabel(this); preview.image->setFixedSize(256, 256); preview.image->setAlignment(Qt::AlignCenter); + auto* settingsBox = new QGroupBox("Settings:", this); + settingsBox->setStyleSheet( + "font-size: 16px; " + "color: white; " + "background: transparent; " + ); + this->settingsLayout = new QFormLayout(settingsBox); + settingsBox->setAlignment(Qt::AlignTop); + settingsBox->setLayout(this->settingsLayout); + + auto* applyButton = new QPushButton("Apply", this); + + connect(applyButton, &QPushButton::clicked, this, [applyButton, this]() { + this->apply(); + }); + layout->addWidget(preview.image); layout->addWidget(preview.title); + layout->addWidget(settingsBox); + layout->addWidget(applyButton); setLayout(layout); } @@ -23,6 +61,8 @@ WallpaperSettingsWidget::WallpaperSettingsWidget(QWidget* parent) void WallpaperSettingsWidget::update(const std::string& selected) { if (selected.empty()) return; + this->currentWallpaperPath = selected; + std::ifstream file(selected + "/project.json"); nlohmann::json wallpaperJSON = nlohmann::json::parse(file); @@ -53,4 +93,109 @@ void WallpaperSettingsWidget::update(const std::string& selected) { preview.image->setPixmap(pixmap); // edit Title preview.title->setText(QString::fromStdString(title)); + + file.close(); + + updateSettings(selected, wallpaperJSON); + apply(); +} + +QCheckBox* createStyledCheckBox(const QString& style) { + auto* cb = new QCheckBox(); + cb->setStyleSheet(style); + return cb; +} + +void WallpaperSettingsWidget::updateSettings(const std::string& wallpaperPath, const nlohmann::json& wallpaper) { + clearSettings(); + + // TODO: add individual settings depending on wallpaper + /* + auto general = wallpaper.find("general"); + if (general != wallpaper.end()) { + if (general->find("properties") != general->end()) { + const auto properties = general->at("properties"); + if (properties != nullptr) { + sLog.out(properties); + } + } + } + */ + + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Mute Audio:", "mute_audio", "--silent", false, false}); + this->currentOptions.push_back({new QSlider(Qt::Horizontal), "Volume:", "volume", "--volume", true, 50}); + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Disable Automute:", "disable_automute", "--noautomute", false, false}); + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Disable Audio Reaction:", "disable_audio_reaction", "--no-audio-processing", false, false}); + this->currentOptions.push_back({new QLineEdit(), "FPS:", "fps", "--fps", true, 30}); + this->currentOptions.push_back({new QComboBox(), "Scaling:", "scaling", "--scaling", true}); + this->currentOptions.push_back({new QComboBox(), "Clamping:", "clamping", "--clamping", true}); + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Disable Mouse:", "diable_mouse", "--disable-mouse", false, false}); + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Disable Parallax", "disable_parallax", "--disable-parallax", false, true}); + this->currentOptions.push_back({createStyledCheckBox(this->checkboxStyleSheet), "Disable Fullscreen Pause:", "disable_fullscreen_pause", "--no-fullscreen-pause", true, false}); + + for (const Option& opt : this->currentOptions) { + this->settingsLayout->addRow(opt.labelName, opt.widget); + + if (auto* cb = dynamic_cast(opt.widget)) { + if (std::holds_alternative(opt.defaultValue)) { + cb->setChecked(std::get(opt.defaultValue)); + } + continue; + } + if (auto* slider = dynamic_cast(opt.widget)) { + if (std::holds_alternative(opt.defaultValue)) { + slider->setValue(std::get(opt.defaultValue)); + } + continue; + } + if (auto* lineEdit = dynamic_cast(opt.widget)) { + if (std::holds_alternative(opt.defaultValue)) { + lineEdit->setText(QString::fromStdString(std::to_string(std::get(opt.defaultValue)))); + } + continue; + } + } +} + +void WallpaperSettingsWidget::clearSettings() { + QLayoutItem* item; + while ((this->settingsLayout->count() != 0) && (item = this->settingsLayout->takeAt(0)) != nullptr) { + if (item->widget()) { + delete item->widget(); + } + if (item->layout()) { + delete item->layout(); + } + delete item; + } + + this->currentOptions.clear(); +} + +void WallpaperSettingsWidget::apply() { + if (currentWallpaperPath.empty()) return; + std::string flags; + + for (const Option& opt : this->currentOptions) { + if (auto* cb = dynamic_cast(opt.widget)) { + if (cb->isChecked()) { + flags.append(opt.flag + " "); + if (opt.flagHasValue) flags.append("true "); + } + continue; + } + if (auto* slider = dynamic_cast(opt.widget)) { + int value = slider->value(); + flags.append(opt.flag + " "); + if (opt.flagHasValue) flags.append(std::to_string(value) + " "); + continue; + } + if (auto* lineEdit = dynamic_cast(opt.widget)) { + std::string value = lineEdit->text().toStdString(); + flags.append(opt.flag + " "); + if (opt.flagHasValue) flags.append(value + " "); + continue; + } + } + emit applySettings(flags); } diff --git a/src/Qt/WallpaperSettingsWidget.h b/src/Qt/WallpaperSettingsWidget.h index 0edfaba..f4715b0 100644 --- a/src/Qt/WallpaperSettingsWidget.h +++ b/src/Qt/WallpaperSettingsWidget.h @@ -1,23 +1,68 @@ #pragma once #include +#include +#include #include +#include #include +#include #include +#include +#include +#include + +class UIWindow; struct Preview { QLabel* image; QLabel* title; }; +struct Option { + QWidget* widget; + QString labelName; + std::string optionName; + std::string flag; + bool flagHasValue; + + std::variant defaultValue; +}; + class WallpaperSettingsWidget : public QWidget { + Q_OBJECT + public: explicit WallpaperSettingsWidget(QWidget* parent = nullptr); void update(const std::string& currentWallpaperPath); private: QVBoxLayout* layout = new QVBoxLayout(this); + QFormLayout* settingsLayout = nullptr; Preview preview = {nullptr, nullptr}; + std::vector