| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- #include "framelessbase.h"
- #include <QCoreApplication>
- #include <QGuiApplication>
- #include <QTimer>
- #include <QVBoxLayout>
- #include <QtCore/QDebug>
- #include <QtCore/QFile>
- #include <QtCore/QTime>
- #include <QtCore/QTimer>
- #include <QtGui/QPainter>
- #include <QtGui/QWindow>
- #include <QtWidgets/QApplication>
- #include <QtWidgets/QPushButton>
- #include <QtWidgets/QStyle>
- #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- #include <QtGui/QActionGroup>
- #else
- #include <QtWidgets/QActionGroup>
- #endif
- #include "widgetframe/windowbar.h"
- #include "widgetframe/windowbutton.h"
- #include "widgets/widgetwindowagent.h"
- 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);
- }
- }
- });
- }
- TMainWindow::TMainWindow(QWidget *parent)
- : QMainWindow(parent)
- {
- setAttribute(Qt::WA_DontCreateNativeAncestors);
- installWindowAgent();
- }
- bool TMainWindow::event(QEvent *event)
- {
- switch (event->type()) {
- case QEvent::WindowActivate: {
- auto menu = menuWidget();
- if (menu) {
- menu->setProperty("bar-active", true);
- style()->polish(menu);
- }
- break;
- }
- case QEvent::WindowDeactivate: {
- auto menu = menuWidget();
- if (menu) {
- menu->setProperty("bar-active", false);
- style()->polish(menu);
- }
- break;
- }
- default:
- break;
- }
- return QMainWindow::event(event);
- }
- void TMainWindow::installWindowAgent()
- {
- // 1. Setup window agent
- windowAgent = new QWK::WidgetWindowAgent(this);
- windowAgent->setup(this);
- auto titleLabel = new QLabel(windowTitle());
- titleLabel->setAlignment(Qt::AlignCenter);
- titleLabel->setObjectName(QStringLiteral("win-title-label"));
- #ifndef Q_OS_MAC
- auto iconButton = new QWK::WindowButton();
- iconButton->setObjectName(QStringLiteral("icon-button"));
- iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
- auto pinButton = new QWK::WindowButton();
- pinButton->setCheckable(true);
- pinButton->setObjectName(QStringLiteral("pin-button"));
- pinButton->setProperty("system-button", true);
- pinButton->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);
- #endif
- auto windowBar = new QWK::WindowBar();
- #ifndef Q_OS_MAC
- windowBar->setIconButton(iconButton);
- windowBar->setPinButton(pinButton);
- windowBar->setMinButton(minButton);
- windowBar->setMaxButton(maxButton);
- windowBar->setCloseButton(closeButton);
- #endif
- windowBar->setTitleLabel(titleLabel);
- windowBar->setHostWidget(this);
- windowAgent->setTitleBar(windowBar);
- #ifndef Q_OS_MAC
- windowAgent->setHitTestVisible(pinButton, true);
- windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
- #endif
- #ifdef Q_OS_MAC
- windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
- static constexpr const int width = 75;
- return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
- });
- #endif
- setMenuWidget(windowBar);
- #ifndef Q_OS_MAC
- connect(this, &QMainWindow::windowTitleChanged, this, [titleLabel](const QString &title) {
- titleLabel->setText(title);
- });
- connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
- if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
- return;
- }
- setWindowFlag(Qt::WindowStaysOnTopHint, pin);
- show();
- pinButton->setChecked(pin);
- });
- connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
- 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
- // manually send leave events to the button.
- emulateLeaveEvent(maxButton);
- });
- connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
- #endif
- }
- TWidget::TWidget(QWidget *parent)
- : QWidget(parent)
- , m_menuWidget(nullptr)
- , m_mainLayout(nullptr)
- {
- m_mainLayout = new QVBoxLayout(this);
- m_mainLayout->setContentsMargins(0, 0, 0, 0);
- m_mainLayout->setSpacing(0);
- setLayout(m_mainLayout);
- setAttribute(Qt::WA_DontCreateNativeAncestors);
- installWindowAgent();
- }
- QWidget *TWidget::menuWidget() const
- {
- return m_menuWidget;
- }
- void TWidget::setMenuWidget(QWidget *widget)
- {
- if (m_menuWidget) {
- m_mainLayout->removeWidget(m_menuWidget);
- delete m_menuWidget;
- }
- // 添加新标题栏到布局顶部
- m_menuWidget = widget;
- if (m_menuWidget) {
- m_mainLayout->insertWidget(0, m_menuWidget); // 插入到第一个位置
- }
- }
- bool TWidget::event(QEvent *event)
- {
- switch (event->type()) {
- case QEvent::WindowActivate: {
- auto menu = menuWidget();
- if (menu) {
- menu->setProperty("bar-active", true);
- style()->polish(menu);
- }
- break;
- }
- case QEvent::WindowDeactivate: {
- auto menu = menuWidget();
- if (menu) {
- menu->setProperty("bar-active", false);
- style()->polish(menu);
- }
- break;
- }
- default:
- break;
- }
- return QWidget::event(event);
- }
- void TWidget::installWindowAgent()
- {
- // 1. Setup window agent
- windowAgent = new QWK::WidgetWindowAgent(this);
- windowAgent->setup(this);
- auto titleLabel = new QLabel();
- titleLabel->setAlignment(Qt::AlignCenter);
- titleLabel->setObjectName(QStringLiteral("win-title-label"));
- #ifndef Q_OS_MAC
- auto iconButton = new QWK::WindowButton();
- iconButton->setObjectName(QStringLiteral("icon-button"));
- iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
- auto pinButton = new QWK::WindowButton();
- pinButton->setCheckable(true);
- pinButton->setObjectName(QStringLiteral("pin-button"));
- pinButton->setProperty("system-button", true);
- pinButton->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);
- #endif
- auto windowBar = new QWK::WindowBar();
- #ifndef Q_OS_MAC
- windowBar->setIconButton(iconButton);
- windowBar->setPinButton(pinButton);
- windowBar->setMinButton(minButton);
- windowBar->setMaxButton(maxButton);
- windowBar->setCloseButton(closeButton);
- #endif
- windowBar->setTitleLabel(titleLabel);
- windowBar->setHostWidget(this);
- windowAgent->setTitleBar(windowBar);
- #ifndef Q_OS_MAC
- windowAgent->setHitTestVisible(pinButton, true);
- windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
- windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
- #endif
- #ifdef Q_OS_MAC
- windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
- static constexpr const int width = 75;
- return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
- });
- #endif
- setMenuWidget(windowBar);
- #ifndef Q_OS_MAC
- connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
- if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
- return;
- }
- setWindowFlag(Qt::WindowStaysOnTopHint, pin);
- show();
- pinButton->setChecked(pin);
- });
- connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
- 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
- // manually send leave events to the button.
- emulateLeaveEvent(maxButton);
- });
- connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
- #endif
- }
|