diff --git a/CMakeLists.txt b/CMakeLists.txt index 65f6dab..8cc2a23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,4 +17,5 @@ pkg_check_modules(hyprutils REQUIRED IMPORTED_TARGET hyprutils) qt_standard_project_setup(REQUIRES 6.5) add_subdirectory(utils/dialog) +add_subdirectory(utils/update-screen) diff --git a/utils/update-screen/CMakeLists.txt b/utils/update-screen/CMakeLists.txt new file mode 100644 index 0000000..abe6da5 --- /dev/null +++ b/utils/update-screen/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.16) + +project(hyprland-update-screen VERSION ${VER} LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 6.5 REQUIRED COMPONENTS Widgets Quick QuickControls2 WaylandClient) +find_package(PkgConfig REQUIRED) + +pkg_check_modules(hyprutils REQUIRED IMPORTED_TARGET hyprutils) + +qt_standard_project_setup(REQUIRES 6.5) + +qt_add_executable(hyprland-update-screen + main.cpp + UpdateScreen.cpp +) + +qt_add_qml_module(hyprland-update-screen + URI org.hyprland.update-screen + VERSION 1.0 + QML_FILES main.qml +) + +target_link_libraries(hyprland-update-screen PRIVATE + Qt6::Widgets Qt6::QuickControls2 Qt6::WaylandClientPrivate PkgConfig::hyprutils +) + + +include(GNUInstallDirs) +install(TARGETS hyprland-update-screen + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/utils/update-screen/UpdateScreen.cpp b/utils/update-screen/UpdateScreen.cpp new file mode 100644 index 0000000..fe5904b --- /dev/null +++ b/utils/update-screen/UpdateScreen.cpp @@ -0,0 +1,17 @@ +#include "UpdateScreen.hpp" +#include +#include +#include +using namespace Hyprutils::String; + +CUpdateScreen::CUpdateScreen(QObject* parent) : QObject(parent) { + ; +} + +void CUpdateScreen::onButtonPress(QString buttonName) { + if (buttonName == "dontshow") { + Hyprutils::OS::CProcess proc("hyprland-dialog", {"--title", "Information", "--text", "If you wish to disable this dialog, set ecosystem:no_update_news to true in your Hyprland config.", "--buttons", "ok"}); + proc.runAsync(); + } else if (buttonName == "quit") + exit(0); +} diff --git a/utils/update-screen/UpdateScreen.hpp b/utils/update-screen/UpdateScreen.hpp new file mode 100644 index 0000000..e9313a7 --- /dev/null +++ b/utils/update-screen/UpdateScreen.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class CUpdateScreen : public QObject { + Q_OBJECT; + QML_NAMED_ELEMENT(UpdateScreen); + QML_SINGLETON; + Q_PROPERTY(QString newVersion MEMBER newVersion CONSTANT); + + public: + explicit CUpdateScreen(QObject* parent = nullptr); + + QString newVersion; + + Q_INVOKABLE void onButtonPress(QString buttonName = ""); +}; diff --git a/utils/update-screen/main.cpp b/utils/update-screen/main.cpp new file mode 100644 index 0000000..45bc5ff --- /dev/null +++ b/utils/update-screen/main.cpp @@ -0,0 +1,54 @@ +#include "UpdateScreen.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace Hyprutils::String; + +int main(int argc, char* argv[]) { + // disable logs to not trash the stdout + qputenv("QT_LOGGING_RULES", QByteArray("*.debug=false;qml=false")); + + auto dialog = new CUpdateScreen(); + + for (int i = 1; i < argc; ++i) { + std::string_view arg = argv[i]; + + if (arg == "--new-version") { + if (i + 1 >= argc) { + std::println(stderr, "--new-version requires a parameter"); + return 1; + } + + dialog->newVersion = argv[i + 1]; + + i++; + continue; + } + + std::println(stderr, "invalid arg {}", argv[i]); + return 1; + } + + if (dialog->newVersion.isEmpty()) { + std::println(stderr, "missing --new-version"); + return 1; + } + + QApplication app(argc, argv); + app.setApplicationName("Hyprland Updated!"); + app.setApplicationDisplayName("Hyprland Updated"); + + if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) + QQuickStyle::setStyle("org.kde.desktop"); + + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("updateScreen", dialog); + engine.load("qrc:/qt/qml/org/hyprland/update-screen/main.qml"); + + return app.exec(); +} diff --git a/utils/update-screen/main.qml b/utils/update-screen/main.qml new file mode 100644 index 0000000..1b86ab2 --- /dev/null +++ b/utils/update-screen/main.qml @@ -0,0 +1,96 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +ApplicationWindow { + id: window + + FontMetrics { id: fontMetrics } + + property var windowPadding: 10 + + minimumWidth: Math.max(fontMetrics.height * 10, mainLayout.Layout.minimumWidth) + mainLayout.anchors.margins * 2 + windowPadding * 2 + minimumHeight: Math.max(fontMetrics.height * 10, mainLayout.Layout.minimumHeight) + mainLayout.anchors.margins * 2 + windowPadding * 2 + maximumWidth: minimumWidth + maximumHeight: minimumHeight + visible: true + + component Separator: Rectangle { + color: Qt.darker(system.windowText, 1.5) + } + + component VSeparator: Separator { + implicitWidth: 1 + Layout.fillHeight: true + Layout.topMargin: fontMetrics.height + Layout.bottomMargin: fontMetrics.height + } + + component HSeparator: Separator { + implicitHeight: 1 + Layout.fillWidth: true + Layout.leftMargin: fontMetrics.height * 8 + Layout.rightMargin: fontMetrics.height * 8 + } + + SystemPalette { + id: system + colorGroup: SystemPalette.Active + } + + ColumnLayout { + id: mainLayout + spacing: fontMetrics.height + + anchors { + fill: parent + margins: 4 + } + + Text { + font.pointSize: fontMetrics.height + color: system.windowText + text: "Hyprland updated to " + updateScreen.newVersion + "!" + Layout.alignment: Qt.AlignHCenter + } + + HSeparator {} + + Text { + color: system.windowText + text: "Hyprland has been updated! 😁

Please check the release notes on GitHub: https://github.com/hyprwm/Hyprland/releases

Every release may come with breaking changes, so if you get any config errors, try checking the latest release notes." + Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Text.AlignHCenter + textFormat: TextEdit.RichText + onLinkActivated: Qt.openUrlExternally(link) + } + + Rectangle { + color: "transparent" + Layout.minimumHeight: 10 + Layout.fillHeight: true + } + + RowLayout { + spacing: 6 + Layout.leftMargin: 20 + Layout.alignment: Qt.AlignRight + + Button { + text: "Don't show this when I update" + onClicked: (e) => { + updateScreen.onButtonPress("dontshow"); + } + } + + Button { + text: "Thanks!" + onClicked: (e) => { + updateScreen.onButtonPress("quit"); + } + } + } + } +}