| | |
| | | #include <QtCore/QFile> |
| | | #include <QtCore/QTime> |
| | | #include <QtCore/QTimer> |
| | | #include <QtGui/QPainter> |
| | | #include <QtWidgets/QApplication> |
| | | #include <QtWidgets/QStyle> |
| | | #include <QtWidgets/QPushButton> |
| | | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | # include <QtGui/QActionGroup> |
| | | #else |
| | | # include <QtWidgets/QActionGroup> |
| | | #endif |
| | | |
| | | #include <QWKCore/styleagent.h> |
| | | #include <QWKWidgets/widgetwindowagent.h> |
| | | |
| | | #include <widgetframe/windowbar.h> |
| | |
| | | |
| | | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { |
| | | installWindowAgent(); |
| | | installStyleAgent(); |
| | | |
| | | auto clockWidget = new ClockWidget(); |
| | | clockWidget->setObjectName(QStringLiteral("clock-widget")); |
| | | clockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
| | | setCentralWidget(clockWidget); |
| | | |
| | | if (QFile qss(QStringLiteral(":/dark-style.qss")); |
| | | qss.open(QIODevice::ReadOnly | QIODevice::Text)) { |
| | | setStyleSheet(QString::fromUtf8(qss.readAll())); |
| | | } |
| | | loadStyleSheet(Dark); |
| | | |
| | | setWindowTitle(tr("Example MainWindow")); |
| | | resize(800, 600); |
| | | } |
| | | |
| | | static inline void emulateLeaveEvent(QWidget *widget) { |
| | |
| | | |
| | | void MainWindow::installWindowAgent() { |
| | | // 1. Setup window agent |
| | | QWK::WidgetWindowAgent *agent = QWK::setupWidgetWindow(this); |
| | | windowAgent = new QWK::WidgetWindowAgent(this); |
| | | windowAgent->setup(this); |
| | | |
| | | // 2. Construct your title bar |
| | | auto menuBar = []() { |
| | | auto menuBar = [this]() { |
| | | auto menuBar = new QMenuBar(); |
| | | |
| | | // Virtual menu |
| | | auto file = new QMenu(tr("File(&F)"), menuBar); |
| | | file->addAction(new QAction(tr("New(&N)"), menuBar)); |
| | | file->addAction(new QAction(tr("Open(&O)"), menuBar)); |
| | | file->addSeparator(); |
| | | |
| | | auto edit = new QMenu(tr("Edit(&E)"), menuBar); |
| | | edit->addAction(new QAction(tr("Undo(&U)"), menuBar)); |
| | | edit->addAction(new QAction(tr("Redo(&R)"), menuBar)); |
| | | |
| | | // Theme action |
| | | auto darkAction = new QAction(tr("Enable dark theme"), menuBar); |
| | | darkAction->setCheckable(true); |
| | | connect(darkAction, &QAction::triggered, this, [this](bool checked) { |
| | | loadStyleSheet(checked ? Dark : Light); // |
| | | }); |
| | | connect(this, &MainWindow::themeChanged, darkAction, [this, darkAction]() { |
| | | darkAction->setChecked(currentTheme == Dark); // |
| | | }); |
| | | |
| | | #ifdef Q_OS_WIN |
| | | auto dwmBlurAction = new QAction(tr("Enable DWM blur"), menuBar); |
| | | dwmBlurAction->setCheckable(true); |
| | | connect(dwmBlurAction, &QAction::triggered, this, [this](bool checked) { |
| | | if (!windowAgent->setWindowAttribute(QStringLiteral("dwm-blur"), checked)) { |
| | | return; |
| | | } |
| | | setProperty("custom-style", checked); |
| | | style()->polish(this); |
| | | }); |
| | | |
| | | auto acrylicAction = new QAction(tr("Enable acrylic material"), menuBar); |
| | | acrylicAction->setCheckable(true); |
| | | connect(acrylicAction, &QAction::triggered, this, [this](bool checked) { |
| | | if (!windowAgent->setWindowAttribute(QStringLiteral("acrylic-material"), true)) { |
| | | return; |
| | | } |
| | | setProperty("custom-style", checked); |
| | | style()->polish(this); |
| | | }); |
| | | |
| | | auto micaAction = new QAction(tr("Enable mica"), menuBar); |
| | | micaAction->setCheckable(true); |
| | | connect(micaAction, &QAction::triggered, this, [this](bool checked) { |
| | | if (!windowAgent->setWindowAttribute(QStringLiteral("mica"), checked)) { |
| | | return; |
| | | } |
| | | setProperty("custom-style", checked); |
| | | style()->polish(this); |
| | | }); |
| | | |
| | | auto micaAltAction = new QAction(tr("Enable mica alt"), menuBar); |
| | | micaAltAction->setCheckable(true); |
| | | connect(micaAltAction, &QAction::triggered, this, [this](bool checked) { |
| | | if (!windowAgent->setWindowAttribute(QStringLiteral("mica-alt"), checked)) { |
| | | return; |
| | | } |
| | | setProperty("custom-style", checked); |
| | | style()->polish(this); |
| | | }); |
| | | |
| | | auto winStyleGroup = new QActionGroup(menuBar); |
| | | winStyleGroup->addAction(dwmBlurAction); |
| | | winStyleGroup->addAction(acrylicAction); |
| | | winStyleGroup->addAction(micaAction); |
| | | winStyleGroup->addAction(micaAltAction); |
| | | #endif |
| | | |
| | | // Real menu |
| | | auto settings = new QMenu(tr("Settings(&S)"), menuBar); |
| | | settings->addAction(darkAction); |
| | | #ifdef Q_OS_WIN |
| | | settings->addSeparator(); |
| | | settings->addAction(dwmBlurAction); |
| | | settings->addAction(acrylicAction); |
| | | settings->addAction(micaAction); |
| | | settings->addAction(micaAltAction); |
| | | #endif |
| | | |
| | | menuBar->addMenu(file); |
| | | menuBar->addMenu(edit); |
| | | menuBar->addMenu(settings); |
| | | return menuBar; |
| | | }(); |
| | | menuBar->setObjectName(QStringLiteral("win-menu-bar")); |
| | |
| | | windowBar->setTitleLabel(titleLabel); |
| | | windowBar->setHostWidget(this); |
| | | |
| | | agent->setTitleBar(windowBar); |
| | | windowAgent->setTitleBar(windowBar); |
| | | #ifndef Q_OS_MAC |
| | | agent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton); |
| | | agent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton); |
| | | agent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton); |
| | | agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton); |
| | | 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 |
| | | agent->setHitTestVisible(menuBar, true); |
| | | windowAgent->setHitTestVisible(menuBar, true); |
| | | |
| | | setMenuWidget(windowBar); |
| | | |
| | | // 3. Adds simulated mouse events to the title bar buttons |
| | | #ifdef Q_OS_WINDOWS |
| | | // Emulate Window system menu button behaviors |
| | | connect(iconButton, &QAbstractButton::clicked, agent, [iconButton, agent] { |
| | | connect(iconButton, &QAbstractButton::clicked, windowAgent, [this, iconButton] { |
| | | iconButton->setProperty("double-click-close", false); |
| | | |
| | | // Pick a suitable time threshold |
| | | QTimer::singleShot(75, agent, [iconButton, agent]() { |
| | | QTimer::singleShot(75, windowAgent, [this, iconButton]() { |
| | | if (iconButton->property("double-click-close").toBool()) |
| | | return; |
| | | agent->showSystemMenu(iconButton->mapToGlobal(QPoint{0, iconButton->height()})); |
| | | windowAgent->showSystemMenu(iconButton->mapToGlobal(QPoint{0, iconButton->height()})); |
| | | }); |
| | | }); |
| | | connect(iconButton, &QWK::WindowButton::doubleClicked, this, [iconButton, this]() { |
| | |
| | | connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close); |
| | | #endif |
| | | } |
| | | |
| | | void MainWindow::installStyleAgent() { |
| | | styleAgent = new QWK::StyleAgent(this); |
| | | } |
| | | |
| | | void MainWindow::loadStyleSheet(Theme theme) { |
| | | if (!styleSheet().isEmpty() && theme == currentTheme) |
| | | return; |
| | | currentTheme = theme; |
| | | |
| | | if (QFile qss(theme == Dark ? QStringLiteral(":/dark-style.qss") |
| | | : QStringLiteral(":/light-style.qss")); |
| | | qss.open(QIODevice::ReadOnly | QIODevice::Text)) { |
| | | setStyleSheet(QString::fromUtf8(qss.readAll())); |
| | | Q_EMIT themeChanged(); |
| | | } |
| | | } |