examples/CMakeLists.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/mainwindow/CMakeLists.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/mainwindow/mainwindow.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/mainwindow/mainwindow.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/shared/CMakeLists.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/shared/widgetframe/CMakeLists.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/shared/widgetframe/windowbar.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/shared/widgetframe/windowbar.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
examples/shared/widgetframe/windowbar_p.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
qmsetup @ 451eab | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/core/contexts/abstractwindowcontext.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/quick/quickwindowagent.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/widgets/widgetwindowagent.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/widgets/widgetwindowagent.h | ●●●●● 补丁 | 查看 | 原始文档 | 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);