diff --git a/CMakeLists.txt b/CMakeLists.txt
index a9f631e..60b03ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,8 +5,15 @@ project(VideoClient LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+# set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTORCC ON)
-find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets OpenGLWidgets Network SerialPort)
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
+include(QWindowKit)
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets OpenGLWidgets Network SerialPort)
qt_standard_project_setup()
diff --git a/cmake/QWindowKit.cmake b/cmake/QWindowKit.cmake
new file mode 100644
index 0000000..01a3380
--- /dev/null
+++ b/cmake/QWindowKit.cmake
@@ -0,0 +1,9 @@
+
+include(fetchcontent)
+ fetchcontent_declare( QWindowKit #库名字
+ GIT_REPOSITORY https://github.com/stdware/qwindowkit # 仓库地址
+ GIT_TAG 1.3.2 # 库版本
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/QWindowKit # 指定库下载地址
+ )
+
+fetchcontent_makeavailable(QWindowKit)
\ No newline at end of file
diff --git a/ext/QWindowKit b/ext/QWindowKit
new file mode 160000
index 0000000..bc03db3
--- /dev/null
+++ b/ext/QWindowKit
@@ -0,0 +1 @@
+Subproject commit bc03db3759e0d8644e626adcbda066ccb2c30062
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e48b1f4..529fd15 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,4 +1,5 @@
+
qt_add_executable(VideoClient
WIN32 MACOSX_BUNDLE
main.cpp
@@ -6,25 +7,44 @@ qt_add_executable(VideoClient
mainwindow.h
mainwindow.ui
global.h global.cpp
- communicationsettingdlg.h communicationsettingdlg.cpp communicationsettingdlg.ui
- commandwidget.h commandwidget.cpp commandwidget.ui
+ communicationsettingdlg.h communicationsettingdlg.cpp
+ commandwidget.h commandwidget.cpp
+)
+
+qt6_add_resources(VideoClient "resources"
+ PREFIX "/"
+ FILES "resources/res.qrc"
+)
+
+qt_add_ui(VideoClient SOURCES
+ commandwidget.ui
+ communicationsettingdlg.ui
)
set(3RDPARTY_DIR ${CMAKE_CURRENT_LIST_DIR}/3rdparty)
set(FFMPEG_DIR ${3RDPARTY_DIR}/ffmpeg)
+
add_subdirectory(video)
add_subdirectory(3rdparty)
+add_subdirectory(shared)
target_link_libraries(VideoClient
PRIVATE
Qt::Core
+ Qt::Gui
Qt::Widgets
Qt6::OpenGLWidgets
Qt6::Network
Qt6::SerialPort
video
+ QWindowKit::Widgets
+ WidgetFrame
)
+# 指定头文件路径
+target_include_directories(VideoClient PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
+
+
include(GNUInstallDirs)
diff --git a/src/commandwidget.cpp b/src/commandwidget.cpp
index a78a4a7..df0f79b 100644
--- a/src/commandwidget.cpp
+++ b/src/commandwidget.cpp
@@ -6,6 +6,9 @@ CommandWidget::CommandWidget(QWidget *parent)
: QWidget(parent), ui(new Ui::CommandWidget) {
ui->setupUi(this);
ui->stopConnectionToolBtn->setDisabled(true);
+ ui->settingToolBtn->setIcon(QIcon(":/images/settings.png"));
+ ui->settingToolBtn->setText("通信设置");
+ ui->settingToolBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
udpSocket = new QUdpSocket(this);
connect(&settingDlg, &CommunicationSettingDlg::sendErrorMessage, this,
diff --git a/src/commandwidget.ui b/src/commandwidget.ui
index be9fd87..023afc0 100644
--- a/src/commandwidget.ui
+++ b/src/commandwidget.ui
@@ -6,7 +6,7 @@
0
0
- 897
+ 1039
105
@@ -24,7 +24,7 @@
4
- 2
+ 4
-
@@ -93,6 +93,9 @@
-
+
+ 6
+
12
diff --git a/src/communicationsettingdlg.cpp b/src/communicationsettingdlg.cpp
index 1678c77..92bb063 100644
--- a/src/communicationsettingdlg.cpp
+++ b/src/communicationsettingdlg.cpp
@@ -6,6 +6,8 @@ CommunicationSettingDlg::CommunicationSettingDlg(QWidget *parent)
: QDialog(parent), ui(new Ui::CommunicationSettingDlg) {
ui->setupUi(this);
+ this->setWindowTitle("通信设置");
+
initCombobox();
initNetworkSetting();
}
diff --git a/src/communicationsettingdlg.ui b/src/communicationsettingdlg.ui
index 4e09328..32b85e6 100644
--- a/src/communicationsettingdlg.ui
+++ b/src/communicationsettingdlg.ui
@@ -38,19 +38,25 @@
- 2
+ 4
2
- 2
+ 4
2
-
+
+ 4
+
+
+ 4
+
7
diff --git a/src/main.cpp b/src/main.cpp
index 9099e07..4fa58ea 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3,6 +3,7 @@
#include "mainwindow.h"
int main(int argc, char *argv[]) {
+ QGuiApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QApplication a(argc, argv);
MainWindow w;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index dd9bdf2..980c77e 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,13 +1,63 @@
#include "mainwindow.h"
+#include
+#include
+
#include
#include "ui_mainwindow.h"
+#include "widgetframe/windowbar.h"
+#include "widgetframe/windowbutton.h"
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
+ this->setWindowTitle("载荷视频播放软件");
+ // windowAgent = new QWK::WidgetWindowAgent(this);
+ // windowAgent->setup(this);
+ // auto windowBar = new QWK::WindowBar();
+ // auto iconButton = new QWK::WindowButton();
+ /*
+ iconButton->setObjectName(QStringLiteral("icon-button"));
+ iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ auto minButton = new QWK::WindowButton();
+ minButton->setObjectName(QStringLiteral("min-button"));
+ minButton->setProperty("system-button", true);
+ minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ auto maxButton = new QWK::WindowButton();
+ maxButton->setCheckable(true);
+ maxButton->setObjectName(QStringLiteral("max-button"));
+ maxButton->setProperty("system-button", true);
+ maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ auto closeButton = new QWK::WindowButton();
+ closeButton->setObjectName(QStringLiteral("close-button"));
+ closeButton->setProperty("system-button", true);
+ closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ windowBar->setIconButton(iconButton);
+ windowBar->setMinButton(minButton);
+ windowBar->setMaxButton(maxButton);
+ windowBar->setCloseButton(closeButton);
+ windowAgent->setTitleBar(windowBar);
+*/
+
+ // apply the qss
+ QFile qssfile(":/Qss/qss.qss");
+ if (qssfile.open(QFile::ReadOnly)) {
+ // file.open(QFile::ReadOnly);
+ QString style = QLatin1String(qssfile.readAll());
+
+ qApp->setStyleSheet(style);
+ // qDebug()<
+
+
+
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/resources/window-bar/fullscreen.svg b/src/shared/widgetframe/resources/window-bar/fullscreen.svg
new file mode 100644
index 0000000..fff0898
--- /dev/null
+++ b/src/shared/widgetframe/resources/window-bar/fullscreen.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/resources/window-bar/maximize.svg b/src/shared/widgetframe/resources/window-bar/maximize.svg
new file mode 100644
index 0000000..a50c909
--- /dev/null
+++ b/src/shared/widgetframe/resources/window-bar/maximize.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/resources/window-bar/minimize.svg b/src/shared/widgetframe/resources/window-bar/minimize.svg
new file mode 100644
index 0000000..e4e4bfd
--- /dev/null
+++ b/src/shared/widgetframe/resources/window-bar/minimize.svg
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/resources/window-bar/more-line.svg b/src/shared/widgetframe/resources/window-bar/more-line.svg
new file mode 100644
index 0000000..246247f
--- /dev/null
+++ b/src/shared/widgetframe/resources/window-bar/more-line.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/resources/window-bar/restore.svg b/src/shared/widgetframe/resources/window-bar/restore.svg
new file mode 100644
index 0000000..bb6e245
--- /dev/null
+++ b/src/shared/widgetframe/resources/window-bar/restore.svg
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/src/shared/widgetframe/windowbar.cpp b/src/shared/widgetframe/windowbar.cpp
new file mode 100644
index 0000000..362383f
--- /dev/null
+++ b/src/shared/widgetframe/windowbar.cpp
@@ -0,0 +1,298 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#include "windowbar.h"
+#include "windowbar_p.h"
+
+#include
+#include
+#include
+
+namespace QWK {
+
+ WindowBarPrivate::WindowBarPrivate() {
+ w = nullptr;
+ autoTitle = true;
+ autoIcon = false;
+ }
+
+ WindowBarPrivate::~WindowBarPrivate() = default;
+
+ void WindowBarPrivate::init() {
+ Q_Q(WindowBar);
+ layout = new QHBoxLayout();
+ if (QLocale::system().textDirection() == Qt::RightToLeft) {
+ layout->setDirection(QBoxLayout::RightToLeft);
+ }
+
+ layout->setContentsMargins(QMargins());
+ layout->setSpacing(0);
+ for (int i = IconButton; i <= CloseButton; ++i) {
+ insertDefaultSpace(i);
+ }
+ q->setLayout(layout);
+ }
+
+ void WindowBarPrivate::setWidgetAt(int index, QWidget *widget) {
+ auto item = layout->takeAt(index);
+ auto orgWidget = item->widget();
+ if (orgWidget) {
+ orgWidget->deleteLater();
+ }
+ delete item;
+ if (!widget) {
+ insertDefaultSpace(index);
+ } else {
+ layout->insertWidget(index, widget);
+ }
+ }
+
+ QWidget *WindowBarPrivate::takeWidgetAt(int index) {
+ auto item = layout->itemAt(index);
+ auto orgWidget = item->widget();
+ if (orgWidget) {
+ item = layout->takeAt(index);
+ delete item;
+ insertDefaultSpace(index);
+ }
+ return orgWidget;
+ }
+
+ WindowBar::WindowBar(QWidget *parent) : WindowBar(*new WindowBarPrivate(), parent) {
+ }
+
+ WindowBar::~WindowBar() = default;
+
+ QMenuBar *WindowBar::menuBar() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::MenuWidget));
+ }
+
+ QLabel *WindowBar::titleLabel() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::TitleLabel));
+ }
+
+ QAbstractButton *WindowBar::iconButton() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::IconButton));
+ }
+
+ QAbstractButton *WindowBar::minButton() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::MinimumButton));
+ }
+
+ QAbstractButton *WindowBar::maxButton() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::MaximumButton));
+ }
+
+ QAbstractButton *WindowBar::closeButton() const {
+ Q_D(const WindowBar);
+ return static_cast(d->widgetAt(WindowBarPrivate::CloseButton));
+ }
+
+ void WindowBar::setMenuBar(QMenuBar *menuBar) {
+ Q_D(WindowBar);
+ auto org = takeMenuBar();
+ if (org)
+ org->deleteLater();
+ if (!menuBar)
+ return;
+ d->setWidgetAt(WindowBarPrivate::MenuWidget, menuBar);
+ menuBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
+ }
+
+ void WindowBar::setTitleLabel(QLabel *label) {
+ Q_D(WindowBar);
+ auto org = takeTitleLabel();
+ if (org)
+ org->deleteLater();
+ if (!label)
+ return;
+ d->setWidgetAt(WindowBarPrivate::TitleLabel, label);
+ if (d->autoTitle && d->w)
+ label->setText(d->w->windowTitle());
+ label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ }
+
+ void WindowBar::setIconButton(QAbstractButton *btn) {
+ Q_D(WindowBar);
+ auto org = takeIconButton();
+ if (org)
+ org->deleteLater();
+ if (!btn)
+ return;
+ d->setWidgetAt(WindowBarPrivate::IconButton, btn);
+ if (d->autoIcon && d->w)
+ btn->setIcon(d->w->windowIcon());
+ btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ }
+
+ void WindowBar::setMinButton(QAbstractButton *btn) {
+ Q_D(WindowBar);
+ auto org = takeMinButton();
+ if (org)
+ org->deleteLater();
+ if (!btn)
+ return;
+ d->setWidgetAt(WindowBarPrivate::MinimumButton, btn);
+ connect(btn, &QAbstractButton::clicked, this, &WindowBar::minimizeRequested);
+ }
+
+ void WindowBar::setMaxButton(QAbstractButton *btn) {
+ Q_D(WindowBar);
+ auto org = takeMaxButton();
+ if (org)
+ org->deleteLater();
+ if (!btn)
+ return;
+ d->setWidgetAt(WindowBarPrivate::MaximumButton, btn);
+ connect(btn, &QAbstractButton::clicked, this, &WindowBar::maximizeRequested);
+ }
+
+ void WindowBar::setCloseButton(QAbstractButton *btn) {
+ Q_D(WindowBar);
+ auto org = takeCloseButton();
+ if (org)
+ org->deleteLater();
+ if (!btn)
+ return;
+ d->setWidgetAt(WindowBarPrivate::CloseButton, btn);
+ connect(btn, &QAbstractButton::clicked, this, &WindowBar::closeRequested);
+ }
+
+ QMenuBar *WindowBar::takeMenuBar() {
+ Q_D(WindowBar);
+ return static_cast(d->takeWidgetAt(WindowBarPrivate::MenuWidget));
+ }
+
+ QLabel *WindowBar::takeTitleLabel() {
+ Q_D(WindowBar);
+ return static_cast(d->takeWidgetAt(WindowBarPrivate::TitleLabel));
+ }
+
+ QAbstractButton *WindowBar::takeIconButton() {
+ Q_D(WindowBar);
+ return static_cast(d->takeWidgetAt(WindowBarPrivate::IconButton));
+ }
+
+ QAbstractButton *WindowBar::takeMinButton() {
+ Q_D(WindowBar);
+ auto btn = static_cast(d->takeWidgetAt(WindowBarPrivate::MinimumButton));
+ if (!btn) {
+ return nullptr;
+ }
+ disconnect(btn, &QAbstractButton::clicked, this, &WindowBar::minimizeRequested);
+ return btn;
+ }
+
+ QAbstractButton *WindowBar::takeMaxButton() {
+ Q_D(WindowBar);
+ auto btn = static_cast(d->takeWidgetAt(WindowBarPrivate::MaximumButton));
+ if (!btn) {
+ return nullptr;
+ }
+ disconnect(btn, &QAbstractButton::clicked, this, &WindowBar::maximizeRequested);
+ return btn;
+ }
+
+ QAbstractButton *WindowBar::takeCloseButton() {
+ Q_D(WindowBar);
+ auto btn = static_cast(d->takeWidgetAt(WindowBarPrivate::CloseButton));
+ if (!btn) {
+ return nullptr;
+ }
+ disconnect(btn, &QAbstractButton::clicked, this, &WindowBar::closeRequested);
+ return btn;
+ }
+
+ QWidget *WindowBar::hostWidget() const {
+ Q_D(const WindowBar);
+ return d->w;
+ }
+
+ void WindowBar::setHostWidget(QWidget *w) {
+ Q_D(WindowBar);
+
+ QWidget *org = d->w;
+ if (org) {
+ org->removeEventFilter(this);
+ }
+ d_ptr->w = w;
+ if (w) {
+ w->installEventFilter(this);
+ }
+ }
+
+ bool WindowBar::titleFollowWindow() const {
+ Q_D(const WindowBar);
+ return d->autoTitle;
+ }
+
+ void WindowBar::setTitleFollowWindow(bool value) {
+ Q_D(WindowBar);
+ d->autoTitle = value;
+ }
+
+ bool WindowBar::iconFollowWindow() const {
+ Q_D(const WindowBar);
+ return d->autoIcon;
+ }
+
+ void WindowBar::setIconFollowWindow(bool value) {
+ Q_D(WindowBar);
+ d->autoIcon = value;
+ }
+
+ bool WindowBar::eventFilter(QObject *obj, QEvent *event) {
+ Q_D(WindowBar);
+ auto w = d->w;
+ if (obj == w) {
+ QAbstractButton *iconBtn = iconButton();
+ QLabel *label = titleLabel();
+ QAbstractButton *maxBtn = maxButton();
+ switch (event->type()) {
+ case QEvent::WindowIconChange: {
+ if (d_ptr->autoIcon && iconBtn) {
+ iconBtn->setIcon(w->windowIcon());
+ iconChanged(w->windowIcon());
+ }
+ break;
+ }
+ case QEvent::WindowTitleChange: {
+ if (d_ptr->autoTitle && label) {
+ label->setText(w->windowTitle());
+ titleChanged(w->windowTitle());
+ }
+ break;
+ }
+ case QEvent::WindowStateChange: {
+ if (maxBtn) {
+ maxBtn->setChecked(w->isMaximized());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return QWidget::eventFilter(obj, event);
+ }
+
+ void WindowBar::titleChanged(const QString &text) {
+ Q_UNUSED(text)
+ }
+
+ void WindowBar::iconChanged(const QIcon &icon){Q_UNUSED(icon)}
+
+ WindowBar::WindowBar(WindowBarPrivate &d, QWidget *parent)
+ : QFrame(parent), d_ptr(&d) {
+ d.q_ptr = this;
+
+ d.init();
+ }
+
+}
diff --git a/src/shared/widgetframe/windowbar.h b/src/shared/widgetframe/windowbar.h
new file mode 100644
index 0000000..2e802f2
--- /dev/null
+++ b/src/shared/widgetframe/windowbar.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef WINDOWBAR_H
+#define WINDOWBAR_H
+
+#include
+#include
+#include
+#include
+
+namespace QWK {
+
+ class WindowBarPrivate;
+
+ class WindowBar : public QFrame {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(WindowBar)
+ public:
+ explicit WindowBar(QWidget *parent = nullptr);
+ ~WindowBar();
+
+ public:
+ QMenuBar *menuBar() const;
+ QLabel *titleLabel() const;
+ QAbstractButton *iconButton() const;
+ QAbstractButton *minButton() const;
+ QAbstractButton *maxButton() const;
+ QAbstractButton *closeButton() const;
+
+ void setMenuBar(QMenuBar *menuBar);
+ void setTitleLabel(QLabel *label);
+ void setIconButton(QAbstractButton *btn);
+ void setMinButton(QAbstractButton *btn);
+ void setMaxButton(QAbstractButton *btn);
+ void setCloseButton(QAbstractButton *btn);
+
+ QMenuBar *takeMenuBar();
+ QLabel *takeTitleLabel();
+ QAbstractButton *takeIconButton();
+ QAbstractButton *takeMinButton();
+ QAbstractButton *takeMaxButton();
+ QAbstractButton *takeCloseButton();
+
+ QWidget *hostWidget() const;
+ void setHostWidget(QWidget *w);
+
+ bool titleFollowWindow() const;
+ void setTitleFollowWindow(bool value);
+
+ bool iconFollowWindow() const;
+ void setIconFollowWindow(bool value);
+
+ Q_SIGNALS:
+ void minimizeRequested();
+ void maximizeRequested(bool max = false);
+ void closeRequested();
+
+ protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+ virtual void titleChanged(const QString &text);
+ virtual void iconChanged(const QIcon &icon);
+
+ protected:
+ WindowBar(WindowBarPrivate &d, QWidget *parent = nullptr);
+
+ QScopedPointer d_ptr;
+ };
+
+}
+
+#endif // WINDOWBAR_H
\ No newline at end of file
diff --git a/src/shared/widgetframe/windowbar_p.h b/src/shared/widgetframe/windowbar_p.h
new file mode 100644
index 0000000..36ceb17
--- /dev/null
+++ b/src/shared/widgetframe/windowbar_p.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef WINDOWBARPRIVATE_H
+#define WINDOWBARPRIVATE_H
+
+#include
+
+#include "windowbar.h"
+
+namespace QWK {
+
+ class WindowBarPrivate {
+ Q_DECLARE_PUBLIC(WindowBar)
+ public:
+ WindowBarPrivate();
+ virtual ~WindowBarPrivate();
+
+ void init();
+
+ WindowBar *q_ptr;
+
+ QWidget *w;
+ bool autoTitle;
+ bool autoIcon;
+
+ enum WindowBarItem {
+ IconButton,
+ MenuWidget,
+ TitleLabel,
+ MinimumButton,
+ MaximumButton,
+ CloseButton,
+ };
+
+ QHBoxLayout *layout;
+
+ inline QWidget *widgetAt(int index) const {
+ return layout->itemAt(index)->widget();
+ }
+
+ void setWidgetAt(int index, QWidget *widget);
+
+ QWidget *takeWidgetAt(int index);
+
+ inline void insertDefaultSpace(int index) {
+ layout->insertSpacerItem(index, new QSpacerItem(0, 0));
+ }
+
+ private:
+ Q_DISABLE_COPY(WindowBarPrivate)
+ };
+
+}
+
+#endif // WINDOWBARPRIVATE_H
\ No newline at end of file
diff --git a/src/shared/widgetframe/windowbutton.cpp b/src/shared/widgetframe/windowbutton.cpp
new file mode 100644
index 0000000..f0b2c70
--- /dev/null
+++ b/src/shared/widgetframe/windowbutton.cpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#include "windowbutton.h"
+#include "windowbutton_p.h"
+
+#include
+#include
+
+namespace QWK {
+
+ WindowButtonPrivate::WindowButtonPrivate() = default;
+
+ WindowButtonPrivate::~WindowButtonPrivate() = default;
+
+ 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/src/shared/widgetframe/windowbutton.h b/src/shared/widgetframe/windowbutton.h
new file mode 100644
index 0000000..402b50f
--- /dev/null
+++ b/src/shared/widgetframe/windowbutton.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef WINDOWBUTTON_H
+#define WINDOWBUTTON_H
+
+#include
+
+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 d_ptr;
+ };
+
+}
+
+#endif // WINDOWBUTTON_H
\ No newline at end of file
diff --git a/src/shared/widgetframe/windowbutton_p.h b/src/shared/widgetframe/windowbutton_p.h
new file mode 100644
index 0000000..34aaaaf
--- /dev/null
+++ b/src/shared/widgetframe/windowbutton_p.h
@@ -0,0 +1,31 @@
+// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware)
+// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao)
+// SPDX-License-Identifier: Apache-2.0
+
+#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