#include "SARibbonPannel.h" #include "SARibbonCategory.h" #include "SARibbonElementManager.h" #include "SARibbonGallery.h" #include "SARibbonPannelLayout.h" #include "SARibbonPannelOptionButton.h" #include "SARibbonToolButton.h" #include #include #include #include #include #include #include #include #include #include #ifndef SARibbonPannel_DEBUG_PRINT #define SARibbonPannel_DEBUG_PRINT 0 #endif #define HELP_DRAW_RECT(p, rect) \ do { \ p.save(); \ QPen _pen(Qt::DashLine); \ _pen.setColor(Qt::blue); \ p.setPen(_pen); \ p.setBrush(QBrush()); \ p.drawRect(rect); \ p.restore(); \ } while (0) //=============================================================== // SARibbonPannelLabel //=============================================================== SARibbonPannelLabel::SARibbonPannelLabel(QWidget* parent) : QLabel(parent) { } //=============================================================== // SARibbonPannel::PrivateData //=============================================================== class SARibbonPannel::PrivateData { SA_RIBBON_DECLARE_PUBLIC(SARibbonPannel) public: PrivateData(SARibbonPannel* p); // 根据m_pannelLayoutMode返回gridLayout应该增加的行数 int rowadded(); void createLayout(); // 获取layout SARibbonPannelLayout* pannelLayout() const; // 返回最后一个添加的action对应的button,前提是最后一个是toolbutton,否则返回nullptr SARibbonToolButton* lastAddActionButton(); // 重置labe的字体,这个主要是为了让pannel的标题字体能适应标题高度 void resetTitleLabelFont(); // 标题 QString pannelName() const; void setPannelName(const QString& title); public: bool m_isCanCustomize { true }; ///< 记录是否可自定义 SARibbonPannel::PannelLayoutMode m_pannelLayoutMode { SARibbonPannel::ThreeRowMode }; ///< pannel的布局模式,默认为3行模式ThreeRowMode SARibbonPannelOptionButton* m_optionActionButton { nullptr }; ///< 标题栏的y距离 SARibbonPannelLabel* m_label { nullptr }; }; SARibbonPannel::PrivateData::PrivateData(SARibbonPannel* p) : q_ptr(p) { createLayout(); } int SARibbonPannel::PrivateData::rowadded() { switch (m_pannelLayoutMode) { case SARibbonPannel::ThreeRowMode: return (2); case SARibbonPannel::TwoRowMode: return (3); default: break; } return (2); } void SARibbonPannel::PrivateData::createLayout() { m_label = new SARibbonPannelLabel(q_ptr); m_label->setAlignment(Qt::AlignCenter); SARibbonPannelLayout* lay = new SARibbonPannelLayout(q_ptr); lay->setPannelTitleLabel(m_label); lay->setSpacing(2); lay->setContentsMargins(2, 2, 2, 2); } SARibbonPannelLayout* SARibbonPannel::PrivateData::pannelLayout() const { return qobject_cast< SARibbonPannelLayout* >(q_ptr->layout()); } SARibbonToolButton* SARibbonPannel::PrivateData::lastAddActionButton() { if (SARibbonPannelLayout* lay = pannelLayout()) { return (qobject_cast< SARibbonToolButton* >(lay->lastWidget())); } return (nullptr); } /** * @brief 重置label的字体 * * @note 此函数必须在布局设置后调用 */ void SARibbonPannel::PrivateData::resetTitleLabelFont() { if (SARibbonPannelLayout* lay = pannelLayout()) { int h = lay->pannelTitleHeight(); QFont f = q_ptr->font(); f.setPixelSize(h * 0.8); if (m_label) { m_label->setFont(f); } } } QString SARibbonPannel::PrivateData::pannelName() const { if (m_label) { return m_label->text(); } return (QString()); } void SARibbonPannel::PrivateData::setPannelName(const QString& title) { if (m_label) { m_label->setText(title); } } //================================================== // SARibbonPannel //================================================== SARibbonPannel::SARibbonPannel(QWidget* parent) : QFrame(parent), d_ptr(new SARibbonPannel::PrivateData(this)) { setPannelLayoutMode(ThreeRowMode); } SARibbonPannel::SARibbonPannel(const QString& name, QWidget* parent) : QFrame(parent), d_ptr(new SARibbonPannel::PrivateData(this)) { setPannelLayoutMode(ThreeRowMode); setPannelName(name); } SARibbonPannel::~SARibbonPannel() { } /** * @brief 把action的行属性设置进action中,action自身携带了行属性 * @param action * @param rp */ void SARibbonPannel::setActionRowProportionProperty(QAction* action, SARibbonPannelItem::RowProportion rp) { Q_CHECK_PTR(action); action->setProperty(SA_ActionPropertyName_RowProportion, static_cast< int >(rp)); } /** * @brief 获取action的行属性 * @param action * @return */ SARibbonPannelItem::RowProportion SARibbonPannel::getActionRowProportionProperty(QAction* action) { bool isok = false; int r = action->property(SA_ActionPropertyName_RowProportion).toInt(&isok); if (isok) { return (static_cast< SARibbonPannelItem::RowProportion >(r)); } return (SARibbonPannelItem::Large); } /** * @brief 设置action的ToolButtonPopupMode属性 * @param action * @param popMode */ void SARibbonPannel::setActionToolButtonPopupModeProperty(QAction* action, QToolButton::ToolButtonPopupMode popMode) { Q_CHECK_PTR(action); action->setProperty(SA_ActionPropertyName_ToolButtonPopupMode, static_cast< int >(popMode)); } /** * @brief 获取action的ToolButtonPopupMode属性 * @param action * @return */ QToolButton::ToolButtonPopupMode SARibbonPannel::getActionToolButtonPopupModeProperty(QAction* action) { bool isok = false; int r = action->property(SA_ActionPropertyName_ToolButtonPopupMode).toInt(&isok); if (isok) { return (static_cast< QToolButton::ToolButtonPopupMode >(r)); } return (QToolButton::InstantPopup); } /** * @brief 设置action的ToolButtonStyle属性 * @param action * @param buttonStyle */ void SARibbonPannel::setActionToolButtonStyleProperty(QAction* action, Qt::ToolButtonStyle buttonStyle) { Q_CHECK_PTR(action); action->setProperty(SA_ActionPropertyName_ToolButtonStyle, static_cast< int >(buttonStyle)); } /** * @brief 获取action的ToolButtonStyle属性 * @param action * @return */ Qt::ToolButtonStyle SARibbonPannel::getActionToolButtonStyleProperty(QAction* action) { bool isok = false; int r = action->property(SA_ActionPropertyName_ToolButtonStyle).toInt(&isok); if (isok) { return (static_cast< Qt::ToolButtonStyle >(r)); } return (Qt::ToolButtonIconOnly); } /** * @brief 添加action * * action实际对应了一个toolbutton,如果想找到对应的toolbutton,使用@ref actionToRibbonToolButton * @param action * @param rp 指定action的行占比 * @param popMode 菜单弹出样式 */ void SARibbonPannel::addAction(QAction* action, SARibbonPannelItem::RowProportion rp) { Q_CHECK_PTR(action); setActionRowProportionProperty(action, rp); addAction(action); } /** * @brief 添加一个action * @param act * @param popMode 按钮的样式 * @param rp action在pannel中的占位情况,默认是大图标 */ void SARibbonPannel::addAction(QAction* act, QToolButton::ToolButtonPopupMode popMode, SARibbonPannelItem::RowProportion rp) { Q_CHECK_PTR(act); setActionRowProportionProperty(act, rp); setActionToolButtonPopupModeProperty(act, popMode); addAction(act); } /** @brief 添加大图标 action实际对应了一个toolbutton,如果想找到对应的toolbutton,使用@ref actionToRibbonToolButton @param action */ void SARibbonPannel::addLargeAction(QAction* action) { addAction(action, SARibbonPannelItem::Large); } /** @brief 在三栏模式下,强制加为2栏action @note 在两行模式下,Medium和Small等价 主要应用在ThreeRowMode下 action实际对应了一个toolbutton,如果想找到对应的toolbutton,使用@ref actionToRibbonToolButton @param action */ void SARibbonPannel::addMediumAction(QAction* action) { addAction(action, SARibbonPannelItem::Medium); } /** @brief 添加小图标 action实际对应了一个toolbutton,如果想找到对应的toolbutton,使用@ref actionToRibbonToolButton @param action */ void SARibbonPannel::addSmallAction(QAction* action) { addAction(action, SARibbonPannelItem::Small); } void SARibbonPannel::addSmallAction(QAction* action, QToolButton::ToolButtonPopupMode popMode) { addAction(action, popMode, SARibbonPannelItem::Small); } void SARibbonPannel::addLargeAction(QAction* action, QToolButton::ToolButtonPopupMode popMode) { addAction(action, popMode, SARibbonPannelItem::Large); } void SARibbonPannel::addMediumAction(QAction* action, QToolButton::ToolButtonPopupMode popMode) { addAction(action, popMode, SARibbonPannelItem::Medium); } /** * @brief 生成并添加一个action * * 如果不对此action做操作,SARibbonPannel将管理此action * * @note action的父对象将设置为SARibbonPannel,SARibbonPannel在删除时将会删除子对象,会把这个action也删除, * 如果不想此action也删除,需要对action重新设置父对象 * * @param text action的文字 * @param icon action的图标 * @param popMode 按钮的样式 * @param rp action在pannel中的占位情况,默认是大图标 * @return 返回添加的action */ QAction* SARibbonPannel::addAction(const QString& text, const QIcon& icon, QToolButton::ToolButtonPopupMode popMode, SARibbonPannelItem::RowProportion rp) { QAction* action = new QAction(icon, text, this); addAction(action, popMode, rp); return (action); } /** * @brief 添加一个普通菜单 * @param menu * @param rp * @param popMode,菜单弹出模式,默认InstantPopup模式 * @return */ void SARibbonPannel::addMenu(QMenu* menu, SARibbonPannelItem::RowProportion rp, QToolButton::ToolButtonPopupMode popMode) { Q_CHECK_PTR(menu); QAction* action = menu->menuAction(); action->setIcon(menu->icon()); action->setText(menu->title()); action->setObjectName("action." + menu->objectName()); addAction(action, popMode, rp); } void SARibbonPannel::addLargeMenu(QMenu* menu, QToolButton::ToolButtonPopupMode popMode) { addMenu(menu, SARibbonPannelItem::Large, popMode); } void SARibbonPannel::addSmallMenu(QMenu* menu, QToolButton::ToolButtonPopupMode popMode) { addMenu(menu, SARibbonPannelItem::Small, popMode); } /** * @brief 添加窗口 * * @param w * @param rp * @return 返回action(QWidgetAction) * @note SARibbonPannel并不会管理此窗口内存,在delete SARibbonPannel时,此窗口如果父对象不是SARibbonPannel将不会被删除 */ QAction* SARibbonPannel::addWidget(QWidget* w, SARibbonPannelItem::RowProportion rp) { QWidgetAction* action = new QWidgetAction(this); action->setDefaultWidget(w); action->setIcon(w->windowIcon()); action->setText(w->windowTitle()); action->setObjectName("action." + w->objectName()); w->setAttribute(Qt::WA_Hover); setActionRowProportionProperty(action, rp); addAction(action); return (action); } /** * @brief 添加窗口,占用ribbon的一行 * @param w * @return 返回action(QWidgetAction) */ QAction* SARibbonPannel::addSmallWidget(QWidget* w) { return (addWidget(w, SARibbonPannelItem::Small)); } /** * @brief 添加窗口,占用ribbon的一行 * @param w * @return */ QAction* SARibbonPannel::addMediumWidget(QWidget* w) { return (addWidget(w, SARibbonPannelItem::Medium)); } /** * @brief 添加窗口,占用所有行 * @param w * @return 返回action(QWidgetAction) */ QAction* SARibbonPannel::addLargeWidget(QWidget* w) { return (addWidget(w, SARibbonPannelItem::Large)); } /** * @brief SARibbonPannel::addGallery * @return * @note SARibbonPannel将拥有SARibbonGallery的管理权 */ SARibbonGallery* SARibbonPannel::addGallery(bool expanding) { SARibbonGallery* gallery = RibbonSubElementFactory->createRibbonGallery(this); addWidget(gallery, SARibbonPannelItem::Large); if (expanding) { setExpanding(expanding); } return (gallery); } /** * @brief 添加分割线 * @param top 上边距 @default 6 * @param bottom 下边距 @default 6 */ QAction* SARibbonPannel::addSeparator() { QAction* action = new QAction(this); action->setSeparator(true); setActionRowProportionProperty(action, SARibbonPannelItem::Large); addAction(action); return (action); } /** * @brief 从pannel中把action对应的button提取出来,如果action没有对应的button,就返回nullptr * @param action * @return 如果action没有对应的button,就返回nullptr */ SARibbonToolButton* SARibbonPannel::actionToRibbonToolButton(QAction* action) { #if 0 SARibbonPannelLayout* lay = qobject_cast< SARibbonPannelLayout* >(layout()); if (lay) { int index = lay->indexOf(action); if (index == -1) { return (nullptr); } QLayoutItem* item = lay->takeAt(index); SARibbonToolButton* btn = qobject_cast< SARibbonToolButton* >(item ? item->widget() : nullptr); return (btn); } return (nullptr); #else for (auto obj : qAsConst(children())) { if (obj->isWidgetType()) { if (SARibbonToolButton* btn = qobject_cast< SARibbonToolButton* >(obj)) { if (btn->defaultAction() == action) { return btn; } } } } return (nullptr); #endif } /** * @brief 获取pannel下面的所有toolbutton * @return */ QList< SARibbonToolButton* > SARibbonPannel::ribbonToolButtons() const { const QObjectList& objs = children(); QList< SARibbonToolButton* > res; for (QObject* o : objs) { SARibbonToolButton* b = qobject_cast< SARibbonToolButton* >(o); if (b) { res.append(b); } } return (res); } /** * @brief 设置PannelLayoutMode * @param mode */ void SARibbonPannel::setPannelLayoutMode(SARibbonPannel::PannelLayoutMode mode) { if (d_ptr->m_pannelLayoutMode == mode) { return; } d_ptr->m_pannelLayoutMode = mode; updateItemGeometry(); } SARibbonPannel::PannelLayoutMode SARibbonPannel::pannelLayoutMode() const { return (d_ptr->m_pannelLayoutMode); } /** * @brief 添加操作action,如果要去除,传入nullptr指针即可,SARibbonPannel不会对QAction的所有权进行管理 * @param action * @note 要去除OptionAction直接传入nullptr即可 * @note SARibbonPannel不对QAction的destroy进行关联,如果外部对action进行delete,需要先传入nullptr给addOptionAction */ void SARibbonPannel::setOptionAction(QAction* action) { if (SARibbonPannelLayout* lay = pannelLayout()) { lay->setOptionAction(action); } } /** * @brief 判断是否存在OptionAction * @return 存在返回true */ bool SARibbonPannel::isHaveOptionAction() const { if (SARibbonPannelLayout* lay = pannelLayout()) { return lay->isHaveOptionAction(); } return false; } QSize SARibbonPannel::sizeHint() const { int shWidth = 500; int shHeight = 100; if (QLayout* lay = layout()) { QSize laySize = layout()->sizeHint(); shWidth = laySize.width(); shHeight = laySize.height(); } return QSize(shWidth, shHeight); } QSize SARibbonPannel::minimumSizeHint() const { return (layout()->minimumSize()); } void SARibbonPannel::setToolButtonIconSize(const QSize& s) { if (SARibbonPannelLayout* lay = pannelLayout()) { lay->setToolButtonIconSize(s); } // 对已经管理的QToolButton设置为iconsize iterate([ s ](SARibbonToolButton* t) -> bool { t->setIconSize(s); return true; }); } QSize SARibbonPannel::toolButtonIconSize() const { if (SARibbonPannelLayout* lay = pannelLayout()) { return lay->toolButtonIconSize(); } return QSize(); } /** * @brief 遍历SARibbonPannel下的所有RibbonToolButton,执行函数指针(bool(SARibbonRibbonToolButton*)),函数指针返回false则停止迭代 * @param fp * @return 返回false说明迭代中途退出,返回true则表示迭代完全 */ bool SARibbonPannel::iterate(SARibbonPannel::FpRibbonToolButtonIterate fp) { const QObjectList& ols = children(); for (QObject* obj : ols) { if (SARibbonToolButton* t = qobject_cast< SARibbonToolButton* >(obj)) { if (!fp(t)) { return false; } } } return true; } /** * @brief 把pannel设置为扩展模式,此时会撑大水平区域 * @param isExpanding */ void SARibbonPannel::setExpanding(bool isExpanding) { setSizePolicy(isExpanding ? QSizePolicy::Expanding : QSizePolicy::Preferred, QSizePolicy::Fixed); } /** * @brief 判断此pannel是否为(水平)扩展模式 * @return 是扩展模式返回true */ bool SARibbonPannel::isExpanding() const { QSizePolicy sp = sizePolicy(); return (sp.horizontalPolicy() == QSizePolicy::Expanding); } /** @brief 设置标题栏的高度 @param h */ void SARibbonPannel::setTitleHeight(int h) { if (SARibbonPannelLayout* lay = pannelLayout()) { lay->setPannelTitleHeight(h); } } /** * @brief 标题栏高度 * @return */ int SARibbonPannel::titleHeight() const { if (SARibbonPannelLayout* lay = pannelLayout()) { return lay->pannelTitleHeight(); } return -1; } /** * @brief 判断是否显示标题,只有标题的高度被设置,才会显示标题 * @return */ bool SARibbonPannel::isEnableShowTitle() const { if (SARibbonPannelLayout* lay = pannelLayout()) { return lay->isEnableShowPannelTitle(); } return false; } /** * @brief 是否显示标题,显示标题后,标题的高度需要设置,默认高度为15 * @param on */ void SARibbonPannel::setEnableShowTitle(bool on) { if (SARibbonPannelLayout* lay = pannelLayout()) { return lay->setEnableShowPannelTitle(on); } } /** * @brief action对应的布局index,此操作一般用于移动,其他意义不大 * @param act * @return 没有查到返回-1 */ int SARibbonPannel::actionIndex(QAction* act) const { if (SARibbonPannelLayout* lay = pannelLayout()) { return (lay->indexByAction(act)); } return (-1); } /** * @brief 移动action * @param from 要移动action的位置,通过@ref actionIndex 获取 * @param to 要移动的位置 */ void SARibbonPannel::moveAction(int from, int to) { if (SARibbonPannelLayout* lay = pannelLayout()) { return (lay->move(from, to)); } updateGeometry(); // 通知layout进行重新布局 } /** * @brief 判断是否可以自定义 * @return */ bool SARibbonPannel::isCanCustomize() const { return (d_ptr->m_isCanCustomize); } /** * @brief 设置是否可以自定义 * @param b */ void SARibbonPannel::setCanCustomize(bool b) { d_ptr->m_isCanCustomize = b; } /** * @brief pannel名称 * @return */ QString SARibbonPannel::pannelName() const { return (d_ptr->pannelName()); } /** * @brief pannel的名称 * @param title 标题 * @note 此函数会触发@sa pannelNameChanged 信号 */ void SARibbonPannel::setPannelName(const QString& title) { QString oldName = pannelName(); if (oldName != title) { d_ptr->setPannelName(title); Q_EMIT pannelNameChanged(title); } } /** * @brief 获取大图标的高度 * @return */ int SARibbonPannel::largeButtonHeight() const { const QMargins& mag = contentsMargins(); return height() - mag.top() - mag.bottom() - titleHeight(); } /** * @brief 获取pannel layout * @return */ SARibbonPannelLayout* SARibbonPannel::pannelLayout() const { return d_ptr->pannelLayout(); } /** * @brief 更新布局 */ void SARibbonPannel::updateItemGeometry() { #if SA_DEBUG_PRINT_SIZE_HINT qDebug() << "SARibbonPannel updateItemGeometry,pannelName=" << pannelName(); #endif // 此函数需要添加,否则SARibbonBar::setEnableWordWrap无法刷新按钮 resetToolButtonSize(); if (SARibbonPannelLayout* lay = pannelLayout()) { lay->updateGeomArray(); } } /** @brief 获取category指针,如果没有parent,或者不在category管理,返回nullptr @return */ SARibbonCategory* SARibbonPannel::category() const { return qobject_cast< SARibbonCategory* >(parent()); } /** @brief 获取ribbonBar指针,如果没有返回nullptr @return */ SARibbonBar* SARibbonPannel::ribbonBar() const { if (SARibbonCategory* c = category()) { return c->ribbonBar(); } return nullptr; } /** * @brief 设置按钮之间的间隔 * @param n */ void SARibbonPannel::setSpacing(int n) { if (auto lay = layout()) { lay->setSpacing(n); } } /** * @brief 按钮之间的间隔 * @return */ int SARibbonPannel::spacing() const { if (auto lay = layout()) { return lay->spacing(); } return 0; } /** * @brief pannel高度推荐 * @param fm * @param layMode * @param pannelTitleHeight * @return */ int SARibbonPannel::pannelHeightHint(const QFontMetrics& fm, PannelLayoutMode layMode, int pannelTitleHeight) { int textH = fm.lineSpacing(); // 这里用linespace,因为在换行的情况下,行距是不可忽略的,ribbon的大按钮默认是2行 switch (layMode) { case SARibbonPannel::ThreeRowMode: { // 5.5=(3*1.6+1) (三行),1是给panneltitle预留的 return textH * 4.8 + pannelTitleHeight; } break; case SARibbonPannel::TwoRowMode: { // 3=2*1.6 return textH * 3.2 + pannelTitleHeight; } break; default: { qWarning() << "unknow SARibbonPannel::PannelLayoutMode:" << layMode; } } return (textH * 4.8 + pannelTitleHeight); } /** * @brief 重置按钮的尺寸,在布局改变后(尤其高度变更),按钮的尺寸需要手动变更 */ void SARibbonPannel::resetToolButtonSize() { QList< SARibbonToolButton* > btns = ribbonToolButtons(); for (SARibbonToolButton* b : qAsConst(btns)) { if ((nullptr == b)) { continue; } b->updateRect(); } } bool SARibbonPannel::event(QEvent* e) { #if SA_DEBUG_PRINT_EVENT if (e->type() != QEvent::Paint) { qDebug() << "SARibbonPannel event(" << e->type() << "),name=" << pannelName(); } #endif // if (SARibbonPannelLayout* lay = pannelLayout()) { // if (lay->isDirty() && e->type() == QEvent::LayoutRequest) { // if (QWidget* parw = parentWidget()) { // if (QLayout* pl = parw->layout()) { // pl->invalidate(); // } // } // lay->m_dirty = false; // } // } return QWidget::event(e); } /** * @brief 处理action的事件 * * 这里处理了ActionAdded,ActionChanged,ActionRemoved三个事件 * * ActionAdded时向布局请求,添加action,布局中同时触发了@ref SARibbonPannelLayout::createItem 函数 * 此函数用于生成窗口,例如QRibbonToolButton * * ActionChanged时会让布局重新计算尺寸,并向category请求重新布局,有可能category的所有要重新调整尺寸 * * ActionRemoved会移除布局管理的QLayoutItem,并进行内存清理,这时窗口也会隐藏,同时销毁 * * @param e * @note 所有action事件都会向category请求重新布局 * */ void SARibbonPannel::actionEvent(QActionEvent* e) { QAction* action = e->action(); QWidgetAction* widgetAction = qobject_cast< QWidgetAction* >(action); switch (e->type()) { case QEvent::ActionAdded: { SARibbonPannelLayout* lay = pannelLayout(); if (nullptr != widgetAction) { if (widgetAction->parent() != this) { widgetAction->setParent(this); } } int index = layout()->count(); if (e->before()) { // 说明是插入 index = lay->indexByAction(e->before()); if (-1 == index) { index = layout()->count(); // 找不到的时候就插入到最后 } } lay->insertAction(index, action, getActionRowProportionProperty(action)); // 由于pannel的尺寸发生变化,需要让category也调整 // if (QWidget* parw = parentWidget()) { // if (QLayout* pl = parw->layout()) { // pl->invalidate(); // } // } } break; case QEvent::ActionChanged: { // 让布局重新绘制 layout()->invalidate(); // updateGeometry(); // 由于pannel的尺寸发生变化,需要让category也调整 if (QWidget* parw = parentWidget()) { if (QLayout* pl = parw->layout()) { pl->invalidate(); } //! 强制发送一个resizeevent,让Category能重绘,如果没有这个函数,发现Category的layout虽然设置了invalidate(标记缓存失效) //! 但并没有按顺序在pannel尺寸更新后更新Category的尺寸,导致有些pannel的尺寸识别出现异常 //! 重打印信息上看,pannel的尺寸有进行更新,category的尺寸也进行了更新,但更新的次数和调用invalidate的次数不一样,需要手动触发ResizeEvent //! 尝试过调用QEvent::LayoutRequest没有效果: //! @code //! QEvent* el = new QEvent(QEvent::LayoutRequest); //! QApplication::postEvent(parw, el); //! @endcode //! //! 调用parw->updateGeometry();也没有效果,目前看使用resizeevent是最有效果的 //! QResizeEvent* ersize = new QResizeEvent(parw->size(), QSize()); QApplication::postEvent(parw, ersize); } } break; case QEvent::ActionRemoved: { SARibbonPannelLayout* lay = pannelLayout(); action->disconnect(this); int index = lay->indexByAction(action); if (index != -1) { QLayoutItem* item = lay->takeAt(index); delete item; } // 由于pannel的尺寸发生变化,需要让category也调整 // if (QWidget* parw = parentWidget()) { // if (QLayout* pl = parw->layout()) { // pl->invalidate(); // } // } } break; default: break; } } /** * @brief 追踪字体改变事件,把新字体设置到childwidget中 * @param e */ void SARibbonPannel::changeEvent(QEvent* e) { if (nullptr == e) { return; } if (e->type() == QEvent::FontChange) { QFont f = font(); QList< QWidget* > listWidgets = findChildren< QWidget* >(); for (QWidget* w : listWidgets) { w->setFont(f); } if (QLayout* lay = layout()) { lay->invalidate(); } d_ptr->resetTitleLabelFont(); } QWidget::changeEvent(e); } /** * @brief 获取布局item * @return */ const QList< SARibbonPannelItem* >& SARibbonPannel::ribbonPannelItem() const { return (pannelLayout()->mItems); } /** * @brief 获取最近添加的按钮 * @return 刚才添加的按钮的指针 */ SARibbonToolButton* SARibbonPannel::lastAddActionButton() { return d_ptr->lastAddActionButton(); }