From e18723d66cf470720c29a9d2848150ea1cbe5450 Mon Sep 17 00:00:00 2001 From: Sine Striker <trueful@163.com> Date: 周四, 14 12月 2023 04:49:35 +0800 Subject: [PATCH] Add example resources --- examples/shared/widgetframe/CMakeLists.txt | 5 src/core/contexts/abstractwindowcontext.cpp | 1 src/widgets/widgetwindowagent_win.cpp | 2 examples/mainwindow/CMakeLists.txt | 9 examples/mainwindow/main.cpp | 10 examples/shared/resources/window-bar/more-line.svg | 5 examples/shared/widgetframe/windowbutton.h | 48 ++++ examples/shared/resources/window-bar.qrc | 11 + examples/mainwindow/mainwindow.h | 6 examples/shared/resources/window-bar/icon.svg | 18 + examples/shared/widgetframe/windowbutton.cpp | 92 ++++++++ examples/shared/resources/window-bar/fullscreen.svg | 11 + src/core/contexts/win32windowcontext.cpp | 1 examples/qml/CMakeLists.txt | 7 examples/shared/resources/window-bar/maximize.svg | 12 + examples/shared/widgetframe/windowbutton_p.h | 27 ++ examples/mainwindow/dark-style.qss | 153 +++++++++++++ examples/shared/resources/window-bar/minimize.svg | 11 + examples/shared/resources/window-bar/restore.svg | 16 + examples/mainwindow/mainwindow.qrc | 5 examples/mainwindow/mainwindow.cpp | 170 +++++++++++--- examples/shared/resources/window-bar/close.svg | 15 + examples/CMakeLists.txt | 8 23 files changed, 597 insertions(+), 46 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9c7ff52..4b35d4e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -13,6 +13,10 @@ add_subdirectory(shared) -add_subdirectory(mainwindow) +if(QWINDOWKIT_BUILD_WIDGETS) + add_subdirectory(mainwindow) +endif() -add_subdirectory(qml) \ No newline at end of file +if(QWINDOWKIT_BUILD_QUICK) + add_subdirectory(qml) +endif() \ No newline at end of file diff --git a/examples/mainwindow/CMakeLists.txt b/examples/mainwindow/CMakeLists.txt index 6137ab3..62845fa 100644 --- a/examples/mainwindow/CMakeLists.txt +++ b/examples/mainwindow/CMakeLists.txt @@ -3,7 +3,12 @@ file(GLOB _src *.h *.cpp) qwk_add_example(${PROJECT_NAME} - SOURCES ${_src} + SOURCES ${_src} mainwindow.qrc ../shared/resources/window-bar.qrc QT_LINKS Core Gui Widgets LINKS QWKWidgets WidgetFrame -) \ No newline at end of file +) + +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED TRUE +) diff --git a/examples/mainwindow/dark-style.qss b/examples/mainwindow/dark-style.qss new file mode 100644 index 0000000..43ea3ee --- /dev/null +++ b/examples/mainwindow/dark-style.qss @@ -0,0 +1,153 @@ +/* Window bar */ + +QWK--WindowBar[bar-active=true] { + background-color: #3C3C3C; +} + +QWK--WindowBar[bar-active=false] { + background-color: #505050; +} + + +/* Title label */ + +QWK--WindowBar>QLabel#win-title-label { + padding: 0; + border: none; + color: #ECECEC; + background-color: transparent; +} + + +/* System buttons */ + +QWK--WindowBar>QAbstractButton[system-button=true] { + qproperty-iconSize: 12px 12px; + min-width: 50px; + border: none; + padding: 0; + background-color: transparent; +} + +QWK--WindowBar>QAbstractButton#min-button { + qproperty-iconNormal: url(":/window-bar/minimize.svg"); + qproperty-iconSize: 12px 12px; +} + +QWK--WindowBar>QAbstractButton#min-button:hover, +QWK--WindowBar>QAbstractButton#min-button:pressed { + background-color: rgba(0, 0, 0, 15%); +} + +QWK--WindowBar>QAbstractButton#max-button { + qproperty-iconNormal: url(":/window-bar/maximize.svg"); + qproperty-iconChecked: url(":/window-bar/restore.svg"); +} + +QWK--WindowBar>QAbstractButton#max-button:hover, +QWK--WindowBar>QAbstractButton#max-button:pressed { + background-color: rgba(0, 0, 0, 15%); +} + +QWK--WindowBar>QAbstractButton#close-button { + qproperty-iconNormal: url(":/window-bar/close.svg"); +} + +QWK--WindowBar>QAbstractButton#close-button:hover, +QWK--WindowBar>QAbstractButton#close-button:pressed { + background-color: #e81123; +} + + +/* Icon button */ + +QWK--WindowBar>QAbstractButton#icon-button { + qproperty-iconNormal: url(":/window-bar/icon.svg"); + qproperty-iconSize: 20px 20px; + min-width: 40px; + border: none; + padding: 0; + background-color: transparent; +} + + +/* Menu Bar */ + +QMenuBar { + background-color: transparent; + border: none; +} + +QMenuBar>QToolButton#qt_menubar_ext_button { + qproperty-icon: url(":/window-bar/more-line.svg"); +} + +QMenuBar>QToolButton#qt_menubar_ext_button:hover, +QMenuBar>QToolButton#qt_menubar_ext_button:pressed { + background-color: rgba(255, 255, 255, 10%); +} + +QMenuBar::item { + color: #CCCCCC; + border: none; + padding: 8px 12px; +} + +QMenuBar::item:selected { + background-color: rgba(255, 255, 255, 10%); +} + + +/* Menu */ + +QMenu { + padding: 4px; + background: #303030; + border: 1.25px solid transparent; +} + +QMenu::indicator { + left: 6px; + width: 20px; + height: 20px; +} + +QMenu::icon { + left: 6px; +} + +QMenu::item { + background: transparent; + color: #CCCCCC; + padding: 6px 24px; +} + +QMenu::item:selected { + color: white; + background-color: #0060C0; +} + +QMenu::item:disabled { + color: #666666; + background-color: transparent; +} + +QMenu::separator { + height: 2px; + background-color: #5B5B5B; + margin: 6px 0; +} + + +/* Window */ + +MainWindow { + background-color: #1E1E1E; +} + +QWidget#clock-widget { + font-size: 75px; + color: #FEFEFE; + font-weight: bold; + background-color: transparent; +} \ No newline at end of file diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp index 66f6bee..8813a60 100644 --- a/examples/mainwindow/main.cpp +++ b/examples/mainwindow/main.cpp @@ -1,4 +1,5 @@ #include <QtWidgets/QApplication> +#include <QtGui/QFont> #include <QtCore/QDebug> #include "mainwindow.h" @@ -17,6 +18,15 @@ QGuiApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication a(argc, argv); + +#ifdef Q_OS_WINDOWS + a.setFont([]() { + QFont f("Microsoft YaHei"); + f.setPixelSize(15); + return f; + }()); +#endif + MainWindow w; w.show(); return a.exec(); diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index c18fe5d..882dc9b 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -1,17 +1,23 @@ #include "mainwindow.h" #include <QtCore/QDebug> +#include <QtCore/QFile> #include <QtCore/QTime> +#include <QtCore/QTimer> +#include <QtWidgets/QApplication> +#include <QtWidgets/QStyle> #include <QtWidgets/QPushButton> #include <QWKWidgets/widgetwindowagent.h> #include <widgetframe/windowbar.h> +#include <widgetframe/windowbutton.h> -class ClockWidget : public QPushButton { +class ClockWidget : public QLabel { public: - explicit ClockWidget(QWidget *parent = nullptr) : QPushButton(parent) { + explicit ClockWidget(QWidget *parent = nullptr) : QLabel(parent) { startTimer(100); + setAlignment(Qt::AlignCenter); } ~ClockWidget() override = default; @@ -24,9 +30,79 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { installWindowAgent(); + + auto clockWidget = new ClockWidget(); + clockWidget->setObjectName("clock-widget"); + clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setCentralWidget(clockWidget); + + if (QFile qss(":/dark-style.qss"); qss.open(QIODevice::ReadOnly | QIODevice::Text)) { + setStyleSheet(QString::fromUtf8(qss.readAll())); + } + + setWindowTitle("Example MainWindow"); + resize(640, 480); +} + +static inline void emulateLeaveEvent(QWidget *widget) { + Q_ASSERT(widget); + if (!widget) { + return; + } + QTimer::singleShot(0, widget, [widget]() { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + const QScreen *screen = widget->screen(); +#else + const QScreen *screen = widget->windowHandle()->screen(); +#endif + const QPoint globalPos = QCursor::pos(screen); + if (!QRect(widget->mapToGlobal(QPoint{0, 0}), widget->size()).contains(globalPos)) { + QCoreApplication::postEvent(widget, new QEvent(QEvent::Leave)); + if (widget->testAttribute(Qt::WA_Hover)) { + const QPoint localPos = widget->mapFromGlobal(globalPos); + const QPoint scenePos = widget->window()->mapFromGlobal(globalPos); + static constexpr const auto oldPos = QPoint{}; + const Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)) + const auto event = + new QHoverEvent(QEvent::HoverLeave, scenePos, globalPos, oldPos, modifiers); + Q_UNUSED(localPos); +#elif (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)) + const auto event = new QHoverEvent(QEvent::HoverLeave, localPos, globalPos, oldPos, modifiers); + Q_UNUSED(scenePos); +#else + const auto event = new QHoverEvent(QEvent::HoverLeave, localPos, oldPos, modifiers); + Q_UNUSED(scenePos); +#endif + QCoreApplication::postEvent(widget, event); + } + } + }); } MainWindow::~MainWindow() { +} + +bool MainWindow::event(QEvent *event) { + switch (event->type()) { + case QEvent::WindowActivate: { + auto menu = menuWidget(); + menu->setProperty("bar-active", true); + style()->polish(menu); + break; + } + + case QEvent::WindowDeactivate: { + auto menu = menuWidget(); + menu->setProperty("bar-active", false); + style()->polish(menu); + break; + } + + default: + break; + } + return QMainWindow::event(event); } void MainWindow::installWindowAgent() { @@ -35,37 +111,45 @@ qFatal("Frameless handle failed to initialize."); } - auto titleLabel = new QLabel(); - titleLabel->setAlignment(Qt::AlignCenter); - auto menuBar = []() { auto menuBar = new QMenuBar(); - auto file = new QMenu("File(&F)"); - file->addAction(new QAction("New(&N)")); - file->addAction(new QAction("Open(&O)")); + auto file = new QMenu("File(&F)", menuBar); + file->addAction(new QAction("New(&N)", menuBar)); + file->addAction(new QAction("Open(&O)", menuBar)); - auto edit = new QMenu("Edit(&E)"); - edit->addAction(new QAction("Undo(&U)")); - edit->addAction(new QAction("Redo(&R)")); + auto edit = new QMenu("Edit(&E)", menuBar); + edit->addAction(new QAction("Undo(&U)", menuBar)); + edit->addAction(new QAction("Redo(&R)", menuBar)); menuBar->addMenu(file); menuBar->addMenu(edit); return menuBar; }(); + menuBar->setObjectName("win-menu-bar"); - auto iconButton = new QPushButton("I"); - iconButton->setAttribute(Qt::WA_Hover); - iconButton->setMouseTracking(true); - auto minButton = new QPushButton("鈥�"); - minButton->setAttribute(Qt::WA_Hover); - minButton->setMouseTracking(true); - auto maxButton = new QPushButton("馃棖"); + auto titleLabel = new QLabel(); + titleLabel->setAlignment(Qt::AlignCenter); + titleLabel->setObjectName("win-title-label"); + + auto iconButton = new QWK::WindowButton(); + iconButton->setObjectName("icon-button"); + iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + auto minButton = new QWK::WindowButton(); + minButton->setObjectName("min-button"); + minButton->setProperty("system-button", true); + minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + auto maxButton = new QWK::WindowButton(); maxButton->setCheckable(true); - maxButton->setAttribute(Qt::WA_Hover); - maxButton->setMouseTracking(true); - auto closeButton = new QPushButton("鉁�"); - closeButton->setAttribute(Qt::WA_Hover); - closeButton->setMouseTracking(true); + maxButton->setObjectName("max-button"); + maxButton->setProperty("system-button", true); + maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + auto closeButton = new QWK::WindowButton(); + closeButton->setObjectName("close-button"); + closeButton->setProperty("system-button", true); + closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); auto windowBar = new QWK::WindowBar(); windowBar->setIconButton(iconButton); @@ -83,29 +167,37 @@ agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton); agent->setHitTestVisible(menuBar, true); +#ifdef Q_OS_WINDOWS + // Emulate Window system menu button behaviors + connect(iconButton, &QAbstractButton::clicked, agent, [this, iconButton, agent] { + setProperty("double-click-close", false); + + // Pick a suitable time threshold + QTimer::singleShot(75, this, [this, iconButton, agent]() { + if (property("double-click-close").toBool()) + return; + agent->showSystemMenu(iconButton->mapToGlobal({0, iconButton->height()})); + }); + }); + connect(iconButton, &QWK::WindowButton::doubleClicked, this, [this]() { + setProperty("double-click-close", true); + close(); + }); +#endif + connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized); - connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this](bool max) { + connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) { if (max) { showMaximized(); } else { showNormal(); } + + // It's a Qt issue that if a QAbstractButton::clicked triggers a window's maximization, + // the button remains to be hovered until the mouse move. As a result, we need to + // manully send leave events to the button. + emulateLeaveEvent(maxButton); }); connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close); - - auto clockWidget = new ClockWidget(); - clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(clockWidget, &QAbstractButton::clicked, this, [this]() { - if (!isMaximized()) { - showMaximized(); - } else { - showNormal(); - } - }); - setMenuWidget(windowBar); - setCentralWidget(clockWidget); - setWindowTitle("Example MainWindow"); - // setContentsMargins({0, 1, 0, 0}); - resize(640, 480); } diff --git a/examples/mainwindow/mainwindow.h b/examples/mainwindow/mainwindow.h index 46f23d3..cfed3a6 100644 --- a/examples/mainwindow/mainwindow.h +++ b/examples/mainwindow/mainwindow.h @@ -4,11 +4,15 @@ #include <QtWidgets/QMainWindow> class MainWindow : public QMainWindow { + Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + ~MainWindow() override; protected: + bool event(QEvent *event) override; + +private: void installWindowAgent(); }; diff --git a/examples/mainwindow/mainwindow.qrc b/examples/mainwindow/mainwindow.qrc new file mode 100644 index 0000000..03d122b --- /dev/null +++ b/examples/mainwindow/mainwindow.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>dark-style.qss</file> + </qresource> +</RCC> \ No newline at end of file diff --git a/examples/qml/CMakeLists.txt b/examples/qml/CMakeLists.txt index ed78439..871f04f 100644 --- a/examples/qml/CMakeLists.txt +++ b/examples/qml/CMakeLists.txt @@ -6,4 +6,9 @@ SOURCES ${_src} QT_LINKS Core Gui Qml Quick LINKS QWKQuick -) \ No newline at end of file +) + +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED TRUE +) diff --git a/examples/shared/resources/window-bar.qrc b/examples/shared/resources/window-bar.qrc new file mode 100644 index 0000000..894de7f --- /dev/null +++ b/examples/shared/resources/window-bar.qrc @@ -0,0 +1,11 @@ +<RCC> + <qresource prefix="/"> + <file>window-bar/close.svg</file> + <file>window-bar/fullscreen.svg</file> + <file>window-bar/icon.svg</file> + <file>window-bar/maximize.svg</file> + <file>window-bar/minimize.svg</file> + <file>window-bar/restore.svg</file> + <file>window-bar/more-line.svg</file> + </qresource> +</RCC> diff --git a/examples/shared/resources/window-bar/close.svg b/examples/shared/resources/window-bar/close.svg new file mode 100644 index 0000000..103d04e --- /dev/null +++ b/examples/shared/resources/window-bar/close.svg @@ -0,0 +1,15 @@ +<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="10.88" height="10.88" + viewBox="0 0 10.88 10.88"> + <defs> + <style> + .cls-1 { + fill: none; + stroke: white; + stroke-miterlimit: 10; + stroke-width: 1.25px; + } + </style> + </defs> + <line class="cls-1" x1="0.44" y1="0.44" x2="10.44" y2="10.44" /> + <line class="cls-1" x1="0.44" y1="10.44" x2="10.44" y2="0.44" /> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/fullscreen.svg b/examples/shared/resources/window-bar/fullscreen.svg new file mode 100644 index 0000000..fff0898 --- /dev/null +++ b/examples/shared/resources/window-bar/fullscreen.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1594017175519" + class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1933" + xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"> + <defs> + <style type="text/css"></style> + </defs> + <path + d="M874.666667 128h-170.666667a21.333333 21.333333 0 0 0 0 42.666667h119.168l-176.917333 176.917333a21.333333 21.333333 0 1 0 30.165333 30.165333L853.333333 200.832V320a21.333333 21.333333 0 0 0 42.666667 0V149.333333a21.333333 21.333333 0 0 0-21.333333-21.333333zM347.584 646.250667L170.666667 823.168V704a21.333333 21.333333 0 0 0-42.666667 0v170.666667a21.333333 21.333333 0 0 0 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 0-42.666667H200.832l176.917333-176.917333a21.333333 21.333333 0 0 0-30.165333-30.165333zM874.666667 682.666667a21.333333 21.333333 0 0 0-21.333334 21.333333v119.168l-176.917333-176.917333a21.333333 21.333333 0 0 0-30.165333 30.165333L823.168 853.333333H704a21.333333 21.333333 0 0 0 0 42.666667h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333zM200.832 170.666667H320a21.333333 21.333333 0 0 0 0-42.666667H149.333333a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667a21.333333 21.333333 0 0 0 42.666667 0V200.832l176.917333 176.917333a21.333333 21.333333 0 0 0 30.165333-30.165333z" + fill="#ffffff" p-id="1934"></path> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/icon.svg b/examples/shared/resources/window-bar/icon.svg new file mode 100644 index 0000000..d56bf51 --- /dev/null +++ b/examples/shared/resources/window-bar/icon.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1597412561411" + class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="780" + xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"> + <defs> + <style type="text/css"></style> + </defs> + <path d="M512 384m-170.666667 0a170.666667 170.666667 0 1 0 341.333334 0 170.666667 170.666667 0 1 0-341.333334 0Z" + fill="#009688" p-id="781"></path> + <path d="M341.333333 384h341.333334v128H341.333333z" fill="#E89419" p-id="782"></path> + <path + d="M661.333333 106.666667v85.333333h-46.933333c-51.2 0-25.6-21.333333-102.4-21.333333V85.333333c76.8 0 51.2 21.333333 102.4 21.333334H661.333333z" + fill="#2196F3" p-id="783"></path> + <path d="M85.333333 512h853.333334v362.666667H85.333333z" fill="#FFB74D" p-id="784"></path> + <path + d="M661.333333 725.333333h85.333334v106.666667h-85.333334zM533.333333 725.333333h85.333334v106.666667h-85.333334zM405.333333 725.333333h85.333334v106.666667h-85.333334zM789.333333 725.333333h85.333334v106.666667h-85.333334zM277.333333 725.333333h85.333334v106.666667h-85.333334zM149.333333 725.333333h85.333334v106.666667H149.333333zM661.333333 576h85.333334v106.666667h-85.333334zM533.333333 576h85.333334v106.666667h-85.333334zM405.333333 576h85.333334v106.666667h-85.333334zM618.666667 512h-85.333334v-64c0-23.466667 19.2-42.666667 42.666667-42.666667s42.666667 19.2 42.666667 42.666667v64zM490.666667 512h-85.333334v-64c0-23.466667 19.2-42.666667 42.666667-42.666667s42.666667 19.2 42.666667 42.666667v64zM789.333333 576h85.333334v106.666667h-85.333334zM277.333333 576h85.333334v106.666667h-85.333334zM149.333333 576h85.333334v106.666667H149.333333z" + fill="#B07424" p-id="785"></path> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/maximize.svg b/examples/shared/resources/window-bar/maximize.svg new file mode 100644 index 0000000..a50c909 --- /dev/null +++ b/examples/shared/resources/window-bar/maximize.svg @@ -0,0 +1,12 @@ +<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10"> + <defs> + <style> + .cls-1 { + fill: none; + stroke: white; + stroke-miterlimit: 10; + } + </style> + </defs> + <rect class="cls-1" x="0.5" y="0.5" width="9" height="9" /> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/minimize.svg b/examples/shared/resources/window-bar/minimize.svg new file mode 100644 index 0000000..e4e4bfd --- /dev/null +++ b/examples/shared/resources/window-bar/minimize.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="鍥惧眰_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" + y="0px" viewBox="0 0 10 10" style="enable-background:new 0 0 10 10;" xml:space="preserve"> + <style type="text/css"> + .st0 { + fill: white; + } + </style> + <rect y="4.5" class="st0" width="10" height="1" /> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/more-line.svg b/examples/shared/resources/window-bar/more-line.svg new file mode 100644 index 0000000..246247f --- /dev/null +++ b/examples/shared/resources/window-bar/more-line.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> + <path fill="none" d="M0 0h24v24H0z" /> + <path fill="white" + d="M4.5 10.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S6 12.825 6 12s-.675-1.5-1.5-1.5zm15 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S21 12.825 21 12s-.675-1.5-1.5-1.5zm-7.5 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z" /> +</svg> \ No newline at end of file diff --git a/examples/shared/resources/window-bar/restore.svg b/examples/shared/resources/window-bar/restore.svg new file mode 100644 index 0000000..bb6e245 --- /dev/null +++ b/examples/shared/resources/window-bar/restore.svg @@ -0,0 +1,16 @@ +<svg id="鍥惧眰_1" data-name="鍥惧眰 1" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"> + <defs> + <style> + .cls-1 { + fill: none; + stroke: white; + stroke-miterlimit: 10; + } + </style> + </defs> + <rect class="cls-1" x="0.5" y="2.5" width="9" height="9" /> + <line class="cls-1" x1="2.5" y1="2.5" x2="2.5" y2="0.5" /> + <line class="cls-1" x1="12" y1="0.5" x2="2" y2="0.5" /> + <line class="cls-1" x1="11.5" y1="10" x2="11.5" /> + <line class="cls-1" x1="10" y1="9.5" x2="12" y2="9.5" /> +</svg> \ No newline at end of file diff --git a/examples/shared/widgetframe/CMakeLists.txt b/examples/shared/widgetframe/CMakeLists.txt index ccd7aa6..05ac949 100644 --- a/examples/shared/widgetframe/CMakeLists.txt +++ b/examples/shared/widgetframe/CMakeLists.txt @@ -13,4 +13,9 @@ QT_LINKS Core Gui Widgets ) +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED TRUE +) + target_include_directories(${PROJECT_NAME} PUBLIC . ..) \ No newline at end of file diff --git a/examples/shared/widgetframe/windowbutton.cpp b/examples/shared/widgetframe/windowbutton.cpp new file mode 100644 index 0000000..7d21cb2 --- /dev/null +++ b/examples/shared/widgetframe/windowbutton.cpp @@ -0,0 +1,92 @@ +#include "windowbutton.h" +#include "windowbutton_p.h" + +#include <QtCore/QDebug> +#include <QtGui/QtEvents> + +namespace QWK { + + WindowButtonPrivate::WindowButtonPrivate() { + } + + WindowButtonPrivate::~WindowButtonPrivate() { + } + + void WindowButtonPrivate::init() { + } + + void WindowButtonPrivate::reloadIcon() { + Q_Q(WindowButton); + + if (!q->isEnabled() && !iconDisabled.isNull()) { + q->setIcon(iconDisabled); + return; + } + + if (q->isChecked() && !iconChecked.isNull()) { + q->setIcon(iconChecked); + return; + } + + if (!iconNormal.isNull()) { + q->setIcon(iconNormal); + } + } + + WindowButton::WindowButton(QWidget *parent) : WindowButton(*new WindowButtonPrivate(), parent) { + } + + WindowButton::~WindowButton() = default; + + QIcon WindowButton::iconNormal() const { + Q_D(const WindowButton); + return d->iconNormal; + } + + void WindowButton::setIconNormal(const QIcon &icon) { + Q_D(WindowButton); + d->iconNormal = icon; + d->reloadIcon(); + } + + QIcon WindowButton::iconChecked() const { + Q_D(const WindowButton); + return d->iconChecked; + } + + void WindowButton::setIconChecked(const QIcon &icon) { + Q_D(WindowButton); + d->iconChecked = icon; + d->reloadIcon(); + } + + QIcon WindowButton::iconDisabled() const { + Q_D(const WindowButton); + return d->iconDisabled; + } + + void WindowButton::setIconDisabled(const QIcon &icon) { + Q_D(WindowButton); + d->iconDisabled = icon; + d->reloadIcon(); + } + + void WindowButton::checkStateSet() { + Q_D(WindowButton); + d->reloadIcon(); + } + + void WindowButton::mouseDoubleClickEvent(QMouseEvent *event) { + if (event->button() == Qt::LeftButton) { + Q_EMIT doubleClicked(); + } + } + + WindowButton::WindowButton(WindowButtonPrivate &d, QWidget *parent) + : QPushButton(parent), d_ptr(&d) { + d.q_ptr = this; + + d.init(); + } + +} diff --git a/examples/shared/widgetframe/windowbutton.h b/examples/shared/widgetframe/windowbutton.h new file mode 100644 index 0000000..eb42194 --- /dev/null +++ b/examples/shared/widgetframe/windowbutton.h @@ -0,0 +1,48 @@ +#ifndef WINDOWBUTTON_H +#define WINDOWBUTTON_H + +#include "QPushButton.h" + +#include <QtGlobal> + +namespace QWK { + + class WindowButtonPrivate; + + class WindowButton : public QPushButton { + Q_OBJECT + Q_DECLARE_PRIVATE(WindowButton) + Q_PROPERTY(QIcon iconNormal READ iconNormal WRITE setIconNormal FINAL) + Q_PROPERTY(QIcon iconChecked READ iconChecked WRITE setIconChecked FINAL) + Q_PROPERTY(QIcon iconDisabled READ iconDisabled WRITE setIconDisabled FINAL) + public: + explicit WindowButton(QWidget *parent = nullptr); + ~WindowButton(); + + public: + QIcon iconNormal() const; + void setIconNormal(const QIcon &icon); + + QIcon iconChecked() const; + void setIconChecked(const QIcon &icon); + + QIcon iconDisabled() const; + void setIconDisabled(const QIcon &icon); + + Q_SIGNALS: + void doubleClicked(); + + protected: + void checkStateSet() override; + + void mouseDoubleClickEvent(QMouseEvent *event) override; + + protected: + WindowButton(WindowButtonPrivate &d, QWidget *parent = nullptr); + + QScopedPointer<WindowButtonPrivate> d_ptr; + }; + +} + +#endif // WINDOWBUTTON_H \ No newline at end of file diff --git a/examples/shared/widgetframe/windowbutton_p.h b/examples/shared/widgetframe/windowbutton_p.h new file mode 100644 index 0000000..75c5976 --- /dev/null +++ b/examples/shared/widgetframe/windowbutton_p.h @@ -0,0 +1,27 @@ +#ifndef WINDOWBUTTONPRIVATE_H +#define WINDOWBUTTONPRIVATE_H + +#include "windowbutton.h" + +namespace QWK { + + class WindowButtonPrivate { + Q_DECLARE_PUBLIC(WindowButton) + public: + WindowButtonPrivate(); + virtual ~WindowButtonPrivate(); + + void init(); + + WindowButton *q_ptr; + + QIcon iconNormal; + QIcon iconChecked; + QIcon iconDisabled; + + void reloadIcon(); + }; + +} + +#endif // WINDOWBUTTONPRIVATE_H \ No newline at end of file diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp index 2a68081..155f0af 100644 --- a/src/core/contexts/abstractwindowcontext.cpp +++ b/src/core/contexts/abstractwindowcontext.cpp @@ -195,6 +195,7 @@ map.insert(QStringLiteral("inactiveDark"), kSampleColorSet.inactiveDark); return; } + default: break; } diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 86ec6bd..a2340ac 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -849,6 +849,7 @@ QPoint{m_windowHandle->width(), 0} }); painter.restore(); + return; } default: { diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp index 2a67ebb..ccac368 100644 --- a/src/widgets/widgetwindowagent_win.cpp +++ b/src/widgets/widgetwindowagent_win.cpp @@ -81,7 +81,7 @@ ®ion, }; ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook, args); - return true; + break; } case QEvent::WindowStateChange: { -- Gitblit v1.9.1