instAdmin/Cpp/GisDes/SaRibbon/SARibbonBar/SARibbonMainWindow.cpp

379 lines
11 KiB
C++
Raw Normal View History

2024-10-29 22:24:50 +08:00
#include "SARibbonMainWindow.h"
#include "SARibbonBar.h"
#include "SARibbonElementManager.h"
#include "SARibbonTabBar.h"
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QHash>
#include <QWindowStateChangeEvent>
#include <QScreen>
#include "SARibbonSystemButtonBar.h"
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
#include <QWKWidgets/widgetwindowagent.h>
#include "SARibbonButtonGroupWidget.h"
#include "SARibbonQuickAccessBar.h"
#include "SARibbonStackedWidget.h"
#else
#include "SAFramelessHelper.h"
#endif
/**
* @brief The SARibbonMainWindowPrivate class
*/
class SARibbonMainWindow::PrivateData
{
SA_RIBBON_DECLARE_PUBLIC(SARibbonMainWindow)
public:
PrivateData(SARibbonMainWindow* p);
void installFrameless(SARibbonMainWindow* p);
public:
SARibbonTheme mCurrentRibbonTheme { SARibbonTheme::RibbonThemeOffice2021Blue };
SARibbonSystemButtonBar* mWindowButtonGroup { nullptr };
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
QWK::WidgetWindowAgent* mFramelessHelper { nullptr };
#else
SAFramelessHelper* mFramelessHelper { nullptr };
#endif
SARibbonMainWindowEventFilter* mEventFilter { nullptr };
};
SARibbonMainWindow::PrivateData::PrivateData(SARibbonMainWindow* p) : q_ptr(p)
{
}
void SARibbonMainWindow::PrivateData::installFrameless(SARibbonMainWindow* p)
{
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
mFramelessHelper = new QWK::WidgetWindowAgent(p);
mFramelessHelper->setup(p);
#else
mFramelessHelper = new SAFramelessHelper(p);
#endif
}
//===================================================
// SARibbonMainWindow
//===================================================
SARibbonMainWindow::SARibbonMainWindow(QWidget* parent, bool useRibbon, const Qt::WindowFlags flags)
: QMainWindow(parent, flags), d_ptr(new SARibbonMainWindow::PrivateData(this))
{
connect(qApp, &QApplication::primaryScreenChanged, this, &SARibbonMainWindow::onPrimaryScreenChanged);
if (useRibbon) {
d_ptr->installFrameless(this);
setRibbonBar(createRibbonBar());
setRibbonTheme(ribbonTheme());
}
}
SARibbonMainWindow::~SARibbonMainWindow()
{
}
/**
* @brief ribbonbar使ribbon模式nullptr
* @return
*/
SARibbonBar* SARibbonMainWindow::ribbonBar() const
{
return qobject_cast< SARibbonBar* >(menuWidget());
}
/**
* @brief ribbonbar
* @param bar
*/
void SARibbonMainWindow::setRibbonBar(SARibbonBar* ribbon)
{
QWidget* old = QMainWindow::menuWidget();
if (old) {
// 如果之前已经设置了menubar要把之前的删除
old->deleteLater();
}
QMainWindow::setMenuWidget(ribbon);
const int th = ribbon->titleBarHeight();
// 设置window按钮
if (nullptr == d_ptr->mWindowButtonGroup) {
d_ptr->mWindowButtonGroup = RibbonSubElementFactory->createWindowButtonGroup(this);
// SARibbonSystemButtonBar的eventfilter捕获mainwindow的事件
// 通过eventerfilter来处理mainwindow的事件避免用户错误的继承resizeEvent导致systembar的位置异常
installEventFilter(d_ptr->mWindowButtonGroup);
}
SARibbonSystemButtonBar* sysBar = d_ptr->mWindowButtonGroup;
sysBar->setWindowStates(windowState());
sysBar->setWindowTitleHeight(th);
sysBar->raise(); // 确保sysbar在最顶层避免第二次设置ribbonbar的时候被ribbonbar覆盖了sysbar
sysBar->show();
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
auto helper = d_ptr->mFramelessHelper;
helper->setTitleBar(ribbon);
// 以下这些窗口,需要允许点击
helper->setHitTestVisible(sysBar); // IMPORTANT!
helper->setHitTestVisible(ribbon->ribbonTabBar()); // IMPORTANT!
helper->setHitTestVisible(ribbon->rightButtonGroup()); // IMPORTANT!
helper->setHitTestVisible(ribbon->applicationButton()); // IMPORTANT!
helper->setHitTestVisible(ribbon->quickAccessBar()); // IMPORTANT!
helper->setHitTestVisible(ribbon->ribbonStackedWidget()); // IMPORTANT!
#if SARIBBON_ENABLE_SNAP_LAYOUT
if (sysBar->closeButton()) {
helper->setSystemButton(QWK::WindowAgentBase::Close, sysBar->closeButton());
}
if (sysBar->minimizeButton()) {
helper->setSystemButton(QWK::WindowAgentBase::Minimize, sysBar->minimizeButton());
}
if (sysBar->maximizeButton()) {
helper->setSystemButton(QWK::WindowAgentBase::Maximize, sysBar->maximizeButton());
}
#endif
#else
// 捕获ribbonbar的事件
ribbon->installEventFilter(this);
// 设置窗体的标题栏高度
d_ptr->mFramelessHelper->setTitleHeight(th);
d_ptr->mFramelessHelper->setRubberBandOnResize(false);
#endif
if (!d_ptr->mEventFilter) {
d_ptr->mEventFilter = new SARibbonMainWindowEventFilter(this);
installEventFilter(d_ptr->mEventFilter);
}
// 最后要提升,否则新加入的会被覆盖
if (d_ptr->mWindowButtonGroup) {
d_ptr->mWindowButtonGroup->raise();
}
}
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
/**
* @brief ribbon中有自定义的窗口在标题栏等非点击区域加入后
* @param w
* @param visible
*/
void SARibbonMainWindow::setFramelessHitTestVisible(QWidget* w, bool visible)
{
auto helper = d_ptr->mFramelessHelper;
helper->setHitTestVisible(const_cast<QWidget*>(w), visible);
}
#else
SAFramelessHelper* SARibbonMainWindow::framelessHelper()
{
return (d_ptr->mFramelessHelper);
}
#endif
bool SARibbonMainWindow::eventFilter(QObject* obj, QEvent* e)
{
#if SARIBBON_USE_3RDPARTY_FRAMELESSHELPER
#else
// 这个过滤是为了把ribbonBar上的动作传递到mainwindow再传递到frameless
// 由于ribbonbar会遮挡掉frameless的区域导致frameless无法捕获这些消息
// 因此必须ribbonBar()->installEventFilter(this);
// 20240101发现installEventFilter后SARibbonMainWindow没有执行这个回调
if (obj == ribbonBar()) {
switch (e->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
case QEvent::Leave:
case QEvent::HoverMove:
case QEvent::MouseButtonDblClick:
QApplication::sendEvent(this, e);
default:
break;
}
}
#endif
return (QMainWindow::eventFilter(obj, e));
}
/**
* @brief
* @return
*/
SARibbonSystemButtonBar* SARibbonMainWindow::windowButtonBar() const
{
return d_ptr->mWindowButtonGroup;
}
/**
* @brief
*/
void SARibbonMainWindow::updateWindowFlag(Qt::WindowFlags flags)
{
if (SARibbonSystemButtonBar* g = d_ptr->mWindowButtonGroup) {
g->updateWindowFlag(flags);
}
}
/**
* @brief SARibbonMainWindow::setRibbonTheme
*
* 使QTimer投放到队列最后执行即可
* @code
* QTimer::singleShot(0, this, [ this ]() { this->setRibbonTheme(SARibbonMainWindow::RibbonThemeDark); });
* @endcode
* @param theme
*/
void SARibbonMainWindow::setRibbonTheme(SARibbonTheme theme)
{
sa_set_ribbon_theme(this, theme);
d_ptr->mCurrentRibbonTheme = theme;
if (SARibbonBar* bar = ribbonBar()) {
auto theme = ribbonTheme();
// 尺寸修正
switch (theme) {
case SARibbonTheme::RibbonThemeWindows7:
case SARibbonTheme::RibbonThemeOffice2013:
case SARibbonTheme::RibbonThemeOffice2016Blue:
case SARibbonTheme::RibbonThemeDark:
case SARibbonTheme::RibbonThemeDark2: {
//! 在设置qss后需要针对margin信息重新设置进SARibbonTabBar中
//! office2013.qss的margin信息如下设置
//! margin-top: 0px;
//! margin-right: 0px;
//! margin-left: 5px;
//! margin-bottom: 0px;
SARibbonTabBar* tab = bar->ribbonTabBar();
if (!tab) {
break;
}
tab->setTabMargin(QMargins(5, 0, 0, 0));
} break;
case SARibbonTheme::RibbonThemeOffice2021Blue: {
SARibbonTabBar* tab = bar->ribbonTabBar();
if (!tab) {
break;
}
//! 在设置qss后需要针对margin信息重新设置进SARibbonTabBar中
//! office2021.qss的margin信息如下设置
//! margin-top: 0px;
//! margin-right: 5px;
//! margin-left: 5px;
//! margin-bottom: 0px;
tab->setTabMargin(QMargins(5, 0, 5, 0));
}
default:
break;
}
// 上下文标签颜色设置,以及基线颜色设置
switch (theme) {
case SARibbonTheme::RibbonThemeWindows7:
case SARibbonTheme::RibbonThemeOffice2013:
case SARibbonTheme::RibbonThemeDark:
bar->setContextCategoryColorList(QList< QColor >()); //< 设置空颜色列表会重置为默认色系
break;
case SARibbonTheme::RibbonThemeOffice2016Blue:
bar->setContextCategoryColorList(QList< QColor >() << QColor(18, 64, 120)); //< 设置空颜色列表会重置为默认色系
break;
case SARibbonTheme::RibbonThemeOffice2021Blue:
bar->setContextCategoryColorList(QList< QColor >() << QColor(209, 207, 209)); //< 设置空颜色列表会重置为默认色系
break;
default:
break;
}
// 基线颜色设置
if (SARibbonTheme::RibbonThemeOffice2013 == theme) {
bar->setTabBarBaseLineColor(QColor(186, 201, 219));
} else {
bar->setTabBarBaseLineColor(QColor());
}
}
}
SARibbonTheme SARibbonMainWindow::ribbonTheme() const
{
return (d_ptr->mCurrentRibbonTheme);
}
bool SARibbonMainWindow::isUseRibbon() const
{
return (nullptr != ribbonBar());
}
/**
* @brief ribbonbar的工厂函数
*
* SARibbonBarRibbon实例
* @return
*/
SARibbonBar* SARibbonMainWindow::createRibbonBar()
{
SARibbonBar* bar = RibbonSubElementFactory->createRibbonBar(this);
bar->setContentsMargins(3, 0, 3, 0);
return bar;
}
/**
* @brief
* @param screen
*/
void SARibbonMainWindow::onPrimaryScreenChanged(QScreen* screen)
{
Q_UNUSED(screen);
// 主屏幕切换后,从新计算所有尺寸
if (SARibbonBar* bar = ribbonBar()) {
qDebug() << "Primary Screen Changed";
bar->updateRibbonGeometry();
}
}
void sa_set_ribbon_theme(QWidget* w, SARibbonTheme theme)
{
QFile file;
switch (theme) {
case SARibbonTheme::RibbonThemeWindows7:
file.setFileName(":/theme/resource/theme-win7.qss");
break;
case SARibbonTheme::RibbonThemeOffice2013:
file.setFileName(":/theme/resource/theme-office2013.qss");
break;
case SARibbonTheme::RibbonThemeOffice2016Blue:
file.setFileName(":/theme/resource/theme-office2016-blue.qss");
break;
case SARibbonTheme::RibbonThemeOffice2021Blue:
file.setFileName(":/theme/resource/theme-office2021-blue.qss");
break;
case SARibbonTheme::RibbonThemeDark:
file.setFileName(":/theme/resource/theme-dark.qss");
break;
case SARibbonTheme::RibbonThemeDark2:
file.setFileName(":/theme/resource/theme-dark2.qss");
break;
default:
file.setFileName(":/theme/resource/theme-office2013.qss");
break;
}
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
// 有反馈用qstring接住文件内容再设置进去才能生效qt5.7版本)
QString qss = QString::fromUtf8(file.readAll());
w->setStyleSheet(qss);
}
//----------------------------------------------------
// SARibbonMainWindowEventFilter
//----------------------------------------------------
SARibbonMainWindowEventFilter::SARibbonMainWindowEventFilter(QObject* par) : QObject(par)
{
}
bool SARibbonMainWindowEventFilter::eventFilter(QObject* obj, QEvent* e)
{
if (e) {
if (e->type() == QEvent::Resize) {
if (SARibbonMainWindow* m = qobject_cast< SARibbonMainWindow* >(obj)) {
if (SARibbonBar* ribbon = m->ribbonBar()) {
ribbon->setFixedWidth(m->size().width());
}
}
}
}
return QObject::eventFilter(obj, e);
}