Sine Striker
2023-12-05 f8975a7d449bac21a2fdbc1a8ca85d1f5b99b362
Implement mainwindow example
9个文件已修改
5个文件已添加
543 ■■■■■ 已修改文件
examples/CMakeLists.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.cpp 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/shared/CMakeLists.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/shared/widgetframe/CMakeLists.txt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/shared/widgetframe/windowbar.cpp 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/shared/widgetframe/windowbar.h 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/shared/widgetframe/windowbar_p.h 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
qmsetup @ 451eab 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/abstractwindowcontext.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/CMakeLists.txt
@@ -1 +1,3 @@
add_subdirectory(shared)
add_subdirectory(mainwindow)
examples/mainwindow/CMakeLists.txt
@@ -11,5 +11,5 @@
qm_configure_target(${PROJECT_NAME}
    SOURCES ${_src}
    QT_LINKS Core Gui Widgets
    LINKS QWKWidgets
    LINKS QWKWidgets WidgetFrame
)
examples/mainwindow/mainwindow.cpp
@@ -1,15 +1,96 @@
#include "mainwindow.h"
#include <QtCore/QDebug>
#include <QtCore/QTime>
#include <QtWidgets/QPushButton>
#include <QWKWidgets/widgetwindowagent.h>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    auto agent = new QWK::WidgetWindowAgent(this);
    if (!agent->setup(this)) {
        qDebug() << "Frameless handle failed to initialize.";
#include <widgetframe/windowbar.h>
class ClockWidget : public QPushButton {
public:
    explicit ClockWidget(QWidget *parent = nullptr) : QPushButton(parent) {
        startTimer(100);
    }
    ~ClockWidget() override = default;
protected:
    void timerEvent(QTimerEvent *event) override {
        setText(QTime::currentTime().toString(QStringLiteral("hh:mm:ss")));
    }
};
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    installWindowAgent();
}
MainWindow::~MainWindow() {
}
void MainWindow::installWindowAgent() {
    auto agent = new QWK::WidgetWindowAgent(this);
    if (!agent->setup(this)) {
        qDebug() << "Frameless handle failed to initialize.";
        return;
    }
    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 edit = new QMenu("Edit(&E)");
        edit->addAction(new QAction("Undo(&U)"));
        edit->addAction(new QAction("Redo(&R)"));
        menuBar->addMenu(file);
        menuBar->addMenu(edit);
        return menuBar;
    }();
    auto iconButton = new QPushButton("I");
    auto minButton = new QPushButton("—");
    auto maxButton = new QPushButton("🗖");
    maxButton->setCheckable(true);
    auto closeButton = new QPushButton("✖");
    auto windowBar = new QWK::WindowBar();
    windowBar->setIconButton(iconButton);
    windowBar->setMinButton(minButton);
    windowBar->setMaxButton(maxButton);
    windowBar->setCloseButton(closeButton);
    windowBar->setMenuBar(menuBar);
    windowBar->setTitleLabel(titleLabel);
    windowBar->setHostWidget(this);
    agent->setTitleBar(windowBar);
    agent->setSystemButton(QWK::CoreWindowAgent::WindowIcon, iconButton);
    agent->setSystemButton(QWK::CoreWindowAgent::Minimize, minButton);
    agent->setSystemButton(QWK::CoreWindowAgent::Maximize, maxButton);
    agent->setSystemButton(QWK::CoreWindowAgent::Close, closeButton);
    agent->setHitTestVisible(menuBar, true);
    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this](bool max) {
        if (max) {
            showMaximized();
        } else {
            showNormal();
        }
    });
    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
    auto clockWidget = new ClockWidget();
    clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setMenuWidget(windowBar);
    setCentralWidget(clockWidget);
    setWindowTitle("Example MainWindow");
    resize(1024, 768);
}
examples/mainwindow/mainwindow.h
@@ -7,6 +7,9 @@
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
protected:
    void installWindowAgent();
};
#endif // MAINWINDOW_H
examples/shared/CMakeLists.txt
New file
@@ -0,0 +1 @@
add_subdirectory(widgetframe)
examples/shared/widgetframe/CMakeLists.txt
New file
@@ -0,0 +1,16 @@
project(WidgetFrame)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
file(GLOB _src *.h *.cpp)
add_library(${PROJECT_NAME} STATIC)
qm_configure_target(${PROJECT_NAME}
    SOURCES ${_src}
    QT_LINKS Core Gui Widgets
)
target_include_directories(${PROJECT_NAME} PUBLIC . ..)
examples/shared/widgetframe/windowbar.cpp
New file
@@ -0,0 +1,288 @@
#include "WindowBar.h"
#include "WindowBar_p.h"
#include <QtCore/QDebug>
#include <QtGui/QtEvents>
namespace QWK {
    WindowBarPrivate::WindowBarPrivate() {
        w = nullptr;
        autoTitle = true;
        autoIcon = false;
    }
    WindowBarPrivate::~WindowBarPrivate() {
    }
    void WindowBarPrivate::init() {
        Q_Q(WindowBar);
        layout = new QHBoxLayout();
        layout->setMargin(0);
        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() {
    }
    QMenuBar *WindowBar::menuBar() const {
        Q_D(const WindowBar);
        return static_cast<QMenuBar *>(d->widgetAt(WindowBarPrivate::MenuWidget));
    }
    QLabel *WindowBar::titleLabel() const {
        Q_D(const WindowBar);
        return static_cast<QLabel *>(d->widgetAt(WindowBarPrivate::TitleLabel));
    }
    QAbstractButton *WindowBar::iconButton() const {
        Q_D(const WindowBar);
        return static_cast<QAbstractButton *>(d->widgetAt(WindowBarPrivate::IconButton));
    }
    QAbstractButton *WindowBar::minButton() const {
        Q_D(const WindowBar);
        return static_cast<QAbstractButton *>(d->widgetAt(WindowBarPrivate::MinimumButton));
    }
    QAbstractButton *WindowBar::maxButton() const {
        Q_D(const WindowBar);
        return static_cast<QAbstractButton *>(d->widgetAt(WindowBarPrivate::MaximumButton));
    }
    QAbstractButton *WindowBar::closeButton() const {
        Q_D(const WindowBar);
        return static_cast<QAbstractButton *>(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<QMenuBar *>(d->takeWidgetAt(WindowBarPrivate::MenuWidget));
    }
    QLabel *WindowBar::takeTitleLabel() {
        Q_D(WindowBar);
        return static_cast<QLabel *>(d->takeWidgetAt(WindowBarPrivate::TitleLabel));
    }
    QAbstractButton *WindowBar::takeIconButton() {
        Q_D(WindowBar);
        return static_cast<QAbstractButton *>(d->takeWidgetAt(WindowBarPrivate::IconButton));
    }
    QAbstractButton *WindowBar::takeMinButton() {
        Q_D(WindowBar);
        auto btn = static_cast<QAbstractButton *>(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<QAbstractButton *>(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<QAbstractButton *>(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();
    }
}
examples/shared/widgetframe/windowbar.h
New file
@@ -0,0 +1,70 @@
#ifndef WINDOWBAR_H
#define WINDOWBAR_H
#include <QFrame>
#include <QAbstractButton>
#include <QMenuBar>
#include <QLabel>
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<WindowBarPrivate> d_ptr;
    };
}
#endif // WINDOWBAR_H
examples/shared/widgetframe/windowbar_p.h
New file
@@ -0,0 +1,50 @@
#ifndef WINDOWBARPRIVATE_H
#define WINDOWBARPRIVATE_H
#include <QBoxLayout>
#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));
        }
    };
}
#endif // WINDOWBARPRIVATE_H
qmsetup
@@ -1 +1 @@
Subproject commit 65369fcf7def72a0aeec59724cdb63e9c5f0475d
Subproject commit 451eabac4f7249fab81295509cbbc4967353a634
src/core/contexts/abstractwindowcontext.cpp
@@ -129,22 +129,22 @@
            if (currentButton && m_delegate->isVisible(currentButton) &&
                m_delegate->isEnabled(currentButton) &&
                m_delegate->mapGeometryToScene(currentButton).contains(pos)) {
                return true;
                return false;
            }
        }
        for (auto widget : m_hitTestVisibleItems) {
            if (widget && m_delegate->isVisible(widget) && m_delegate->isEnabled(widget) &&
                m_delegate->mapGeometryToScene(widget).contains(pos)) {
                return true;
                return false;
            }
        }
        if (hitTestShape().contains(pos)) {
            return true;
            return false;
        }
        return false;
        return true;
    }
}
src/quick/quickwindowagent.h
@@ -28,8 +28,8 @@
        void setSystemButton(SystemButton button, QQuickItem *item);
        bool isHitTestVisible(QQuickItem *item) const;
        void setHitTestVisible(QQuickItem *item, bool visible);
        void setHitTestVisible(const QRect &rect, bool visible);
        void setHitTestVisible(QQuickItem *item, bool visible = true);
        void setHitTestVisible(const QRect &rect, bool visible = true);
    Q_SIGNALS:
        void titleBarWidgetChanged(QQuickItem *item);
src/widgets/widgetwindowagent.cpp
@@ -53,12 +53,12 @@
        Q_EMIT titleBarWidgetChanged(w);
    }
    QWidget *WidgetWindowAgent::systemButton(CoreWindowAgent::SystemButton button) const {
    QWidget *WidgetWindowAgent::systemButton(SystemButton button) const {
        Q_D(const WidgetWindowAgent);
        return static_cast<QWidget *>(d->context->systemButton(button));
    }
    void WidgetWindowAgent::setSystemButton(CoreWindowAgent::SystemButton button, QWidget *w) {
    void WidgetWindowAgent::setSystemButton(SystemButton button, QWidget *w) {
        Q_D(WidgetWindowAgent);
        if (!d->context->setSystemButton(button, w)) {
            return;
src/widgets/widgetwindowagent.h
@@ -27,8 +27,8 @@
        void setSystemButton(SystemButton button, QWidget *w);
        bool isHitTestVisible(QWidget *w) const;
        void setHitTestVisible(QWidget *w, bool visible);
        void setHitTestVisible(const QRect &rect, bool visible);
        void setHitTestVisible(QWidget *w, bool visible = true);
        void setHitTestVisible(const QRect &rect, bool visible = true);
    Q_SIGNALS:
        void titleBarWidgetChanged(QWidget *w);