468 lines
13 KiB
C++
468 lines
13 KiB
C++
#include "SARibbonSystemButtonBar.h"
|
||
#include <QToolButton>
|
||
#include <QResizeEvent>
|
||
#include <QStyle>
|
||
#include <QDebug>
|
||
#include <QScopedPointer>
|
||
#include <QWindowStateChangeEvent>
|
||
#include "SARibbonMainWindow.h"
|
||
#include "SARibbonBar.h"
|
||
#include "SARibbonElementManager.h"
|
||
#include "SARibbonButtonGroupWidget.h"
|
||
|
||
// 为了避免使用此框架的app设置了全局的qpushbutton 的 qss样式影响此按钮,定义了一个类
|
||
|
||
/**
|
||
* @brief The SARibbonSystemButtonBar class
|
||
*/
|
||
class SARibbonSystemButtonBar::PrivateData
|
||
{
|
||
SA_RIBBON_DECLARE_PUBLIC(SARibbonSystemButtonBar)
|
||
public:
|
||
SARibbonSystemToolButton* buttonClose { nullptr };
|
||
SARibbonSystemToolButton* buttonMinimize { nullptr };
|
||
SARibbonSystemToolButton* buttonMaximize { nullptr };
|
||
int mCloseStretch { 4 };
|
||
int mMaxStretch { 3 };
|
||
int mMinStretch { 3 };
|
||
int mWindowButtonWidth { 35 };
|
||
int mTitleBarHeight { 28 };
|
||
Qt::WindowFlags mFlags { Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint };
|
||
SARibbonButtonGroupWidget* mButtonGroup;
|
||
|
||
public:
|
||
PrivateData(SARibbonSystemButtonBar* p) : q_ptr(p)
|
||
{
|
||
mButtonGroup = new SARibbonButtonGroupWidget(p);
|
||
mButtonGroup->setObjectName("SASystemButtonGroup");
|
||
}
|
||
|
||
void setupMinimizeButton(bool on)
|
||
{
|
||
SARibbonSystemButtonBar* par = q_ptr;
|
||
|
||
if (on) {
|
||
if (buttonMinimize) {
|
||
buttonMinimize->deleteLater();
|
||
buttonMinimize = nullptr;
|
||
}
|
||
buttonMinimize = new SARibbonSystemToolButton(par);
|
||
buttonMinimize->setObjectName(QStringLiteral("SAMinimizeWindowButton"));
|
||
buttonMinimize->setFocusPolicy(Qt::NoFocus); // 避免铺抓到
|
||
buttonMinimize->show();
|
||
par->connect(buttonMinimize, &QAbstractButton::clicked, par, &SARibbonSystemButtonBar::minimizeWindow);
|
||
} else {
|
||
if (buttonMinimize) {
|
||
buttonMinimize->deleteLater();
|
||
buttonMinimize = nullptr;
|
||
}
|
||
}
|
||
updateSize();
|
||
}
|
||
|
||
void setupMaximizeButton(bool on)
|
||
{
|
||
SARibbonSystemButtonBar* par = q_ptr;
|
||
|
||
if (on) {
|
||
if (buttonMaximize) {
|
||
buttonMaximize->deleteLater();
|
||
buttonMaximize = nullptr;
|
||
}
|
||
buttonMaximize = new SARibbonSystemToolButton(par);
|
||
buttonMaximize->setObjectName(QStringLiteral("SAMaximizeWindowButton"));
|
||
buttonMaximize->setCheckable(true);
|
||
buttonMaximize->setFocusPolicy(Qt::NoFocus); // 避免铺抓到
|
||
// buttonMaximize->setIconSize(buttonMaximize->size() * mIconscale);
|
||
buttonMaximize->show();
|
||
par->connect(buttonMaximize, &QAbstractButton::clicked, par, &SARibbonSystemButtonBar::maximizeWindow);
|
||
} else {
|
||
if (buttonMaximize) {
|
||
buttonMaximize->deleteLater();
|
||
;
|
||
buttonMaximize = nullptr;
|
||
}
|
||
}
|
||
updateSize();
|
||
}
|
||
|
||
void setupCloseButton(bool on)
|
||
{
|
||
SARibbonSystemButtonBar* par = q_ptr;
|
||
|
||
if (on) {
|
||
if (buttonClose) {
|
||
buttonClose->deleteLater();
|
||
buttonClose = nullptr;
|
||
}
|
||
buttonClose = new SARibbonSystemToolButton(par);
|
||
buttonClose->setObjectName(QStringLiteral("SACloseWindowButton"));
|
||
buttonClose->setFocusPolicy(Qt::NoFocus); // 避免铺抓到
|
||
// buttonClose->setFlat(true);
|
||
par->connect(buttonClose, &QAbstractButton::clicked, par, &SARibbonSystemButtonBar::closeWindow);
|
||
// buttonClose->setIconSize(buttonClose->size() * mIconscale);
|
||
buttonClose->show();
|
||
} else {
|
||
if (buttonClose) {
|
||
buttonClose->deleteLater();
|
||
;
|
||
buttonClose = nullptr;
|
||
}
|
||
}
|
||
updateSize();
|
||
}
|
||
|
||
void updateSize()
|
||
{
|
||
resizeElement(q_ptr->size());
|
||
}
|
||
|
||
void resizeElement(QSize size)
|
||
{
|
||
int x = size.width();
|
||
if (buttonClose) {
|
||
int w = closeButtonWidthHint();
|
||
x -= w;
|
||
buttonClose->setGeometry(x, 0, w, size.height());
|
||
}
|
||
if (buttonMaximize) {
|
||
int w = maxButtonWidthHint();
|
||
x -= w;
|
||
buttonMaximize->setGeometry(x, 0, w, size.height());
|
||
}
|
||
if (buttonMinimize) {
|
||
int w = minButtonWidthHint();
|
||
x -= w;
|
||
buttonMinimize->setGeometry(x, 0, w, size.height());
|
||
}
|
||
if (mButtonGroup) {
|
||
mButtonGroup->setGeometry(0, 0, x, size.height());
|
||
}
|
||
}
|
||
|
||
int closeButtonWidthHint() const
|
||
{
|
||
qreal t = mCloseStretch + mMaxStretch + mMinStretch;
|
||
return (mCloseStretch * (3 * mWindowButtonWidth)) / t;
|
||
}
|
||
|
||
int maxButtonWidthHint() const
|
||
{
|
||
qreal t = mCloseStretch + mMaxStretch + mMinStretch;
|
||
return (mMaxStretch * (3 * mWindowButtonWidth)) / t;
|
||
}
|
||
|
||
int minButtonWidthHint() const
|
||
{
|
||
qreal t = mCloseStretch + mMaxStretch + mMinStretch;
|
||
return (mMinStretch * (3 * mWindowButtonWidth)) / t;
|
||
}
|
||
|
||
QSize sizeHint() const
|
||
{
|
||
int height = mTitleBarHeight;
|
||
if (height < 20) {
|
||
height = 20;
|
||
}
|
||
QSize res(0, 0);
|
||
if (mButtonGroup) {
|
||
res = mButtonGroup->sizeHint();
|
||
}
|
||
res.setHeight(height);
|
||
if (buttonClose) {
|
||
res.setWidth(res.width() + closeButtonWidthHint());
|
||
}
|
||
if (buttonMaximize) {
|
||
res.setWidth(res.width() + maxButtonWidthHint());
|
||
}
|
||
if (buttonMinimize) {
|
||
res.setWidth(res.width() + minButtonWidthHint());
|
||
}
|
||
return res;
|
||
}
|
||
};
|
||
|
||
//===================================================
|
||
// SARibbonSystemToolButton
|
||
//===================================================
|
||
SARibbonSystemToolButton::SARibbonSystemToolButton(QWidget* p) : QToolButton(p)
|
||
{
|
||
setAutoRaise(true);
|
||
}
|
||
//===================================================
|
||
// SARibbonSystemButtonBar
|
||
//===================================================
|
||
SARibbonSystemButtonBar::SARibbonSystemButtonBar(QWidget* parent)
|
||
: QFrame(parent), d_ptr(new SARibbonSystemButtonBar::PrivateData(this))
|
||
{
|
||
updateWindowFlag();
|
||
}
|
||
|
||
/**
|
||
* @brief 构造函数,强制使用flags,而不是用parent的flags进行构造
|
||
* @param parent
|
||
* @param flags
|
||
*/
|
||
SARibbonSystemButtonBar::SARibbonSystemButtonBar(QWidget* parent, Qt::WindowFlags flags)
|
||
: QFrame(parent), d_ptr(new SARibbonSystemButtonBar::PrivateData(this))
|
||
{
|
||
d_ptr->mFlags = flags;
|
||
updateWindowFlag();
|
||
}
|
||
|
||
SARibbonSystemButtonBar::~SARibbonSystemButtonBar()
|
||
{
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::setupMinimizeButton(bool on)
|
||
{
|
||
d_ptr->setupMinimizeButton(on);
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::setupMaximizeButton(bool on)
|
||
{
|
||
d_ptr->setupMaximizeButton(on);
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::setupCloseButton(bool on)
|
||
{
|
||
d_ptr->setupCloseButton(on);
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::updateWindowFlag()
|
||
{
|
||
QWidget* topedWidget = this;
|
||
// 找到最顶层窗口
|
||
while (topedWidget->parentWidget()) {
|
||
topedWidget = topedWidget->parentWidget();
|
||
}
|
||
Qt::WindowFlags flags = topedWidget->windowFlags();
|
||
updateWindowFlag(flags);
|
||
}
|
||
|
||
/**
|
||
* @brief 此函数仅用于控制最小最大化和关闭按钮的显示
|
||
* @param flags
|
||
*/
|
||
void SARibbonSystemButtonBar::updateWindowFlag(Qt::WindowFlags flags)
|
||
{
|
||
d_ptr->mFlags = flags;
|
||
setupMinimizeButton(flags & Qt::WindowMinimizeButtonHint);
|
||
setupMaximizeButton(flags & Qt::WindowMaximizeButtonHint);
|
||
setupCloseButton(flags & Qt::WindowCloseButtonHint);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置按钮的宽度比例,最终按钮宽度将按照此比例进行设置
|
||
* @param close 关闭按钮比例
|
||
* @param max 最大化按钮比例
|
||
* @param min 最小化按钮比例
|
||
*/
|
||
void SARibbonSystemButtonBar::setButtonWidthStretch(int close, int max, int min)
|
||
{
|
||
d_ptr->mMaxStretch = max;
|
||
d_ptr->mMinStretch = min;
|
||
d_ptr->mCloseStretch = close;
|
||
}
|
||
|
||
/**
|
||
* @brief 标题栏高度
|
||
*
|
||
* 标题栏高度会影响sizeHint
|
||
* @param h
|
||
*/
|
||
void SARibbonSystemButtonBar::setWindowTitleHeight(int h)
|
||
{
|
||
d_ptr->mTitleBarHeight = h;
|
||
}
|
||
|
||
/**
|
||
* @brief 标题栏高度
|
||
* @return
|
||
*/
|
||
int SARibbonSystemButtonBar::windowTitleHeight() const
|
||
{
|
||
return d_ptr->mTitleBarHeight;
|
||
}
|
||
|
||
/**
|
||
* @brief 系统按钮的宽度
|
||
* @param w
|
||
*/
|
||
void SARibbonSystemButtonBar::setWindowButtonWidth(int w)
|
||
{
|
||
d_ptr->mWindowButtonWidth = w;
|
||
}
|
||
|
||
/**
|
||
* @brief 系统按钮的宽度
|
||
* @param w
|
||
*/
|
||
int SARibbonSystemButtonBar::windowButtonWidth() const
|
||
{
|
||
return d_ptr->mWindowButtonWidth;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置窗口状态(最大最小化按钮状态)
|
||
* @param s
|
||
*/
|
||
void SARibbonSystemButtonBar::setWindowStates(Qt::WindowStates s)
|
||
{
|
||
if (d_ptr->buttonMaximize) {
|
||
bool on = s.testFlag(Qt::WindowMaximized);
|
||
d_ptr->buttonMaximize->setChecked(on);
|
||
d_ptr->buttonMaximize->setToolTip(on ? tr("Restore") : tr("Maximize"));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 此函数返回的flags仅包括 Qt::WindowCloseButtonHint,Qt::WindowMaximizeButtonHint,Qt::WindowMinimizeButtonHint
|
||
* 三个
|
||
*
|
||
* @return
|
||
*/
|
||
Qt::WindowFlags SARibbonSystemButtonBar::windowButtonFlags() const
|
||
{
|
||
Qt::WindowFlags f = Qt::Widget; // widget是000
|
||
|
||
if (d_ptr->mFlags & Qt::WindowCloseButtonHint) {
|
||
f |= Qt::WindowCloseButtonHint;
|
||
}
|
||
if (d_ptr->mFlags & Qt::WindowMaximizeButtonHint) {
|
||
f |= Qt::WindowMaximizeButtonHint;
|
||
}
|
||
if (d_ptr->mFlags & Qt::WindowMinimizeButtonHint) {
|
||
f |= Qt::WindowMinimizeButtonHint;
|
||
}
|
||
|
||
return (f);
|
||
}
|
||
|
||
QSize SARibbonSystemButtonBar::sizeHint() const
|
||
{
|
||
return (d_ptr->sizeHint());
|
||
}
|
||
|
||
bool SARibbonSystemButtonBar::eventFilter(QObject* obj, QEvent* event)
|
||
{
|
||
if (obj == parent()) {
|
||
// SARibbonMainWindow的事件
|
||
if (event->type() == QEvent::Resize) {
|
||
SARibbonMainWindow* mainWindow = qobject_cast< SARibbonMainWindow* >(obj);
|
||
if (!mainWindow) {
|
||
// 所有事件都不消费
|
||
return QFrame::eventFilter(obj, event);
|
||
}
|
||
SARibbonBar* ribbonBar = mainWindow->ribbonBar();
|
||
if (!ribbonBar) {
|
||
// 所有事件都不消费
|
||
return QFrame::eventFilter(obj, event);
|
||
}
|
||
const int th = ribbonBar->titleBarHeight();
|
||
if (th != height()) {
|
||
setWindowTitleHeight(th);
|
||
}
|
||
QRect fr = mainWindow->geometry();
|
||
QSize wgSizeHint = sizeHint();
|
||
setGeometry(fr.width() - wgSizeHint.width(), 0, wgSizeHint.width(), wgSizeHint.height());
|
||
// 把设置好的尺寸给ribbonbar
|
||
ribbonBar->setWindowButtonGroupSize(size());
|
||
} else if (event->type() == QEvent::WindowStateChange) {
|
||
SARibbonMainWindow* mainWindow = qobject_cast< SARibbonMainWindow* >(obj);
|
||
if (!mainWindow) {
|
||
// 所有事件都不消费
|
||
return QFrame::eventFilter(obj, event);
|
||
}
|
||
setWindowStates(mainWindow->windowState());
|
||
}
|
||
}
|
||
return QFrame::eventFilter(obj, event);
|
||
}
|
||
|
||
QAbstractButton* SARibbonSystemButtonBar::minimizeButton() const
|
||
{
|
||
return d_ptr->buttonMinimize;
|
||
}
|
||
|
||
QAbstractButton* SARibbonSystemButtonBar::maximizeButton() const
|
||
{
|
||
return d_ptr->buttonMaximize;
|
||
}
|
||
|
||
QAbstractButton* SARibbonSystemButtonBar::closeButton() const
|
||
{
|
||
return d_ptr->buttonClose;
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::setIconSize(const QSize& ic)
|
||
{
|
||
d_ptr->mButtonGroup->setIconSize(ic);
|
||
}
|
||
|
||
QSize SARibbonSystemButtonBar::iconSize() const
|
||
{
|
||
return d_ptr->mButtonGroup->iconSize();
|
||
}
|
||
|
||
QAction* SARibbonSystemButtonBar::addAction(QAction* a, Qt::ToolButtonStyle buttonStyle, QToolButton::ToolButtonPopupMode popMode)
|
||
{
|
||
return d_ptr->mButtonGroup->addAction(a, buttonStyle, popMode);
|
||
}
|
||
|
||
QAction* SARibbonSystemButtonBar::addAction(const QString& text,
|
||
const QIcon& icon,
|
||
Qt::ToolButtonStyle buttonStyle,
|
||
QToolButton::ToolButtonPopupMode popMode)
|
||
{
|
||
return d_ptr->mButtonGroup->addAction(text, icon, buttonStyle, popMode);
|
||
}
|
||
|
||
QAction* SARibbonSystemButtonBar::addMenu(QMenu* menu, Qt::ToolButtonStyle buttonStyle, QToolButton::ToolButtonPopupMode popMode)
|
||
{
|
||
return d_ptr->mButtonGroup->addMenu(menu, buttonStyle, popMode);
|
||
}
|
||
|
||
QAction* SARibbonSystemButtonBar::addSeparator()
|
||
{
|
||
return d_ptr->mButtonGroup->addSeparator();
|
||
}
|
||
|
||
QAction* SARibbonSystemButtonBar::addWidget(QWidget* w)
|
||
{
|
||
return d_ptr->mButtonGroup->addWidget(w);
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::resizeEvent(QResizeEvent* e)
|
||
{
|
||
Q_UNUSED(e);
|
||
d_ptr->resizeElement(size());
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::closeWindow()
|
||
{
|
||
if (parentWidget()) {
|
||
parentWidget()->close();
|
||
}
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::minimizeWindow()
|
||
{
|
||
if (parentWidget()) {
|
||
parentWidget()->showMinimized();
|
||
}
|
||
}
|
||
|
||
void SARibbonSystemButtonBar::maximizeWindow()
|
||
{
|
||
QWidget* par = parentWidget();
|
||
|
||
if (par) {
|
||
if (par->isMaximized()) {
|
||
par->showNormal();
|
||
} else {
|
||
par->showMaximized();
|
||
}
|
||
}
|
||
}
|