instAdmin/Cpp/GisDes/SaRibbon/SARibbonBar/SARibbonButtonGroupWidget.cpp
2024-10-29 22:24:50 +08:00

261 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SARibbonButtonGroupWidget.h"
#include <QHBoxLayout>
#include <QDebug>
#include <QMargins>
#include <QChildEvent>
#include <QActionEvent>
#include <QWidgetAction>
#include <QApplication>
#include "SARibbonControlButton.h"
#include "SARibbonElementManager.h"
#include "SARibbonSeparatorWidget.h"
#include "SARibbonPannel.h"
//===================================================
// SARibbonButtonGroupWidget::PrivateData
//===================================================
class SARibbonButtonGroupWidget::PrivateData
{
SA_RIBBON_DECLARE_PUBLIC(SARibbonButtonGroupWidget)
public:
PrivateData(SARibbonButtonGroupWidget* p);
void init();
void removeAction(QAction* a);
public:
QSize mIconSize { 20, 20 };
};
SARibbonButtonGroupWidget::PrivateData::PrivateData(SARibbonButtonGroupWidget* p) : q_ptr(p)
{
}
void SARibbonButtonGroupWidget::PrivateData::init()
{
QHBoxLayout* layout = new QHBoxLayout(q_ptr);
// 上下保留一点间隙
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(1);
q_ptr->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
}
void SARibbonButtonGroupWidget::PrivateData::removeAction(QAction* a)
{
QLayout* lay = q_ptr->layout();
int c = lay->count();
QList< QLayoutItem* > willRemoveItems;
for (int i = 0; i < c; ++i) {
QLayoutItem* item = lay->itemAt(i);
SARibbonControlButton* btn = qobject_cast< SARibbonControlButton* >(item->widget());
if (nullptr == btn) {
continue;
}
if (a == btn->defaultAction()) {
willRemoveItems.push_back(item);
}
}
// 从尾部删除
for (auto i = willRemoveItems.rbegin(); i != willRemoveItems.rend(); ++i) {
lay->removeItem(*i);
}
}
//===================================================
// SARibbonButtonGroupWidget
//===================================================
SARibbonButtonGroupWidget::SARibbonButtonGroupWidget(QWidget* parent)
: QFrame(parent), d_ptr(new SARibbonButtonGroupWidget::PrivateData(this))
{
d_ptr->init();
}
SARibbonButtonGroupWidget::~SARibbonButtonGroupWidget()
{
}
/**
* @brief 设置图标尺寸
* @param iconSize
*/
void SARibbonButtonGroupWidget::setIconSize(const QSize& ic)
{
d_ptr->mIconSize = ic;
iterate([ ic ](SARibbonControlButton* btn) -> bool {
btn->setIconSize(ic);
return true;
});
}
/**
* @brief 图标尺寸
* @return
*/
QSize SARibbonButtonGroupWidget::iconSize() const
{
return d_ptr->mIconSize;
}
QAction* SARibbonButtonGroupWidget::addAction(QAction* a, Qt::ToolButtonStyle buttonStyle, QToolButton::ToolButtonPopupMode popMode)
{
SARibbonPannel::setActionToolButtonStyleProperty(a, buttonStyle);
SARibbonPannel::setActionToolButtonPopupModeProperty(a, popMode);
QWidget::addAction(a);
return (a);
}
/**
* @brief 生成action
* @note action的所有权归SARibbonButtonGroupWidget
* @param text
* @param icon
* @param popMode
* @return
*/
QAction* SARibbonButtonGroupWidget::addAction(const QString& text, const QIcon& icon, Qt::ToolButtonStyle buttonStyle, QToolButton::ToolButtonPopupMode popMode)
{
QAction* a = new QAction(icon, text, this);
addAction(a, buttonStyle, popMode);
return (a);
}
QAction* SARibbonButtonGroupWidget::addMenu(QMenu* menu, Qt::ToolButtonStyle buttonStyle, QToolButton::ToolButtonPopupMode popMode)
{
QAction* a = menu->menuAction();
addAction(a, buttonStyle, popMode);
return (a);
}
QAction* SARibbonButtonGroupWidget::addSeparator()
{
QAction* a = new QAction(this);
a->setSeparator(true);
addAction(a);
return (a);
}
QAction* SARibbonButtonGroupWidget::addWidget(QWidget* w)
{
QWidgetAction* a = new QWidgetAction(this);
a->setDefaultWidget(w);
w->setAttribute(Qt::WA_Hover);
addAction(a);
return (a);
}
SARibbonControlButton* SARibbonButtonGroupWidget::actionToRibbonControlToolButton(QAction* action)
{
SARibbonControlButton* res = nullptr;
iterate([ &res, action ](SARibbonControlButton* btn) -> bool {
if (btn->defaultAction() == action) {
res = btn;
return false; // 返回false退出迭代
}
return true;
});
return (res);
}
QSize SARibbonButtonGroupWidget::sizeHint() const
{
return (layout()->sizeHint());
}
QSize SARibbonButtonGroupWidget::minimumSizeHint() const
{
return (layout()->minimumSize());
}
/**
* @brief 此函数会遍历SARibbonButtonGroupWidget下的所有SARibbonControlButton执行函数指针(bool(SARibbonControlButton*))函数指针返回false则停止迭代
* @param fp
* @return 中途迭代退出返回false
*/
bool SARibbonButtonGroupWidget::iterate(SARibbonButtonGroupWidget::FpButtonIterate fp)
{
QLayout* lay = layout();
int c = lay->count();
for (int i = 0; i < c; ++i) {
auto item = lay->itemAt(i);
if (!item) {
continue;
}
SARibbonControlButton* btn = qobject_cast< SARibbonControlButton* >(item->widget());
if (!btn) {
continue;
}
if (!fp(btn)) {
return false;
}
}
return true;
}
/**
* @brief 处理action的事件
*
* 这里处理了ActionAddedActionChangedActionRemoved三个事件
* ActionAdded时会生成窗口
* @param e
*/
void SARibbonButtonGroupWidget::actionEvent(QActionEvent* e)
{
QAction* a = e->action();
if (!a) {
return;
}
switch (e->type()) {
case QEvent::ActionAdded: {
QWidget* w = nullptr;
if (QWidgetAction* widgetAction = qobject_cast< QWidgetAction* >(a)) {
widgetAction->setParent(this);
w = widgetAction->requestWidget(this);
if (w != nullptr) {
w->setAttribute(Qt::WA_LayoutUsesWidgetRect);
w->show();
}
} else if (a->isSeparator()) {
SARibbonSeparatorWidget* sp = RibbonSubElementFactory->createRibbonSeparatorWidget(this);
w = sp;
}
// 不是widget自动生成ButtonTyle
if (!w) {
SARibbonControlButton* button = RibbonSubElementFactory->createRibbonControlButton(this);
button->setAutoRaise(true);
button->setIconSize(d_ptr->mIconSize);
button->setFocusPolicy(Qt::NoFocus);
button->setDefaultAction(a);
// 属性设置
QToolButton::ToolButtonPopupMode popMode = SARibbonPannel::getActionToolButtonPopupModeProperty(a);
button->setPopupMode(popMode);
Qt::ToolButtonStyle buttonStyle = SARibbonPannel::getActionToolButtonStyleProperty(a);
button->setToolButtonStyle(buttonStyle);
// 根据QAction的属性设置按钮的大小
connect(button, &SARibbonToolButton::triggered, this, &SARibbonButtonGroupWidget::actionTriggered);
w = button;
}
layout()->addWidget(w);
updateGeometry();
} break;
case QEvent::ActionChanged: {
// 让布局重新绘制
layout()->invalidate();
updateGeometry();
} break;
case QEvent::ActionRemoved: {
d_ptr->removeAction(e->action());
updateGeometry();
} break;
default:
break;
}
QFrame::actionEvent(e);
}