You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

451 lines
16 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#ifndef SARIBBONBAR_H
#define SARIBBONBAR_H
#include "SARibbonCategory.h"
#include "SARibbonContextCategory.h"
#include "SARibbonGlobal.h"
#include <QMenuBar>
#include <QScopedPointer>
#include <QVariant>
class QAction;
class QAbstractButton;
class SARibbonElementFactory;
class SARibbonTabBar;
class SARibbonButtonGroupWidget;
class SARibbonQuickAccessBar;
class SARibbonStackedWidget;
/**
@brief SARibbonBar继承于QMenuBar,在SARibbonMainWindow中直接替换了原来的QMenuBar
通过setRibbonStyle函数设置ribbon的风格:
@code
void setRibbonStyle(RibbonStyles v);
@endcode
SARibbonBar参考office和wps提供了四种风格的Ribbon模式,@ref SARibbonBar::RibbonStyles
如果想ribbon占用的空间足够小WpsLiteStyleTwoRow模式能比OfficeStyle节省35%的高度空间
如何生成ribbon?先看看一个传统的Menu/ToolBar是如何生成的
@code
void MainWindow::MainWindow()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QToolBar *fileToolBar = addToolBar(tr("File"));
//生成action
QAction *newAct = new QAction(newIcon, tr("&New"), this);
fileMenu->addAction(newAct);
fileToolBar->addAction(newAct);
QAction *openAct = new QAction(openIcon, tr("&Open..."), this);
fileMenu->addAction(openAct);
fileToolBar->addAction(openAct);
}
@endcode
传统的Menu/ToolBar主要通过QMenu的addMenu添加菜单,通过QMainWindow::addToolBar生成QToolBar,
再把QAction设置进QMenu和QToolBar中
SARibbonBar和传统方法相似不过相对于传统的Menu/ToolBar QMenu和QToolBar是平级的
Ribbon是有明显的层级关系SARibbonBar下面是 @ref SARibbonCategory
SARibbonCategory下面是@ref SARibbonPannel SARibbonPannel下面是@ref SARibbonToolButton
SARibbonToolButton管理着QAction
因此生成一个ribbon只需以下几个函数
@code
SARibbonCategory * SARibbonBar::addCategoryPage(const QString& title);
SARibbonPannel * SARibbonCategory::addPannel(const QString& title);
SARibbonToolButton * SARibbonPannel::addLargeAction(QAction *action);
SARibbonToolButton * SARibbonPannel::addSmallAction(QAction *action);
@endcode
因此生成步骤如下:
@code
//成员变量
SARibbonCategory* categoryMain;
SARibbonPannel* FilePannel;
//建立ui
void setupRibbonUi()
{
......
//ribbonwindow为SARibbonMainWindow
SARibbonBar* ribbon = ribbonwindow->ribbonBar();
ribbon->setRibbonStyle(SARibbonBar::WpsLiteStyle);
//添加一个Main标签
categoryMain = ribbon->addCategoryPage(QStringLiteral("Main"));
//Main标签下添加一个File Pannel
FilePannel = categoryMain->addPannel(QStringLiteral("FilePannel"));
//开始为File Pannel添加action
FilePannel->addLargeAction(actionNew);
FilePannel->addLargeAction(actionOpen);
FilePannel->addLargeAction(actionSave);
FilePannel->addSmallAction(actionImportMesh);
FilePannel->addSmallAction(actionImportGeometry);
}
@endcode
*/
class SA_RIBBON_EXPORT SARibbonBar : public QMenuBar
{
Q_OBJECT
SA_RIBBON_DECLARE_PRIVATE(SARibbonBar)
friend class SARibbonMainWindow;
Q_PROPERTY(RibbonStyles ribbonStyle READ currentRibbonStyle WRITE setRibbonStyle)
Q_PROPERTY(bool minimumMode READ isMinimumMode WRITE setMinimumMode)
Q_PROPERTY(bool minimumModeButton READ haveShowMinimumModeButton WRITE showMinimumModeButton)
Q_PROPERTY(QColor windowTitleTextColor READ windowTitleTextColor WRITE setWindowTitleTextColor)
Q_PROPERTY(QColor tabBarBaseLineColor READ tabBarBaseLineColor WRITE setTabBarBaseLineColor)
Q_PROPERTY(Qt::Alignment windowTitleAligment READ windowTitleAligment WRITE setWindowTitleAligment)
Q_PROPERTY(bool enableWordWrap READ isEnableWordWrap WRITE setEnableWordWrap)
Q_PROPERTY(bool enableShowPannelTitle READ isEnableShowPannelTitle WRITE setEnableShowPannelTitle)
Q_PROPERTY(bool tabOnTitle READ isTabOnTitle WRITE setTabOnTitle)
Q_PROPERTY(SARibbonPannel::PannelLayoutMode pannelLayoutMode READ pannelLayoutMode WRITE setPannelLayoutMode)
public:
enum RibbonStyleFlag
{
RibbonStyleLoose = 0x0001, // bit:0000 0001
RibbonStyleCompact = 0x0002, // bit:0000 0010
RibbonStyleThreeRow = 0x0010, // bit:0001 0000
RibbonStyleTwoRow = 0x0020, // bit:0010 0000
RibbonStyleLooseThreeRow = RibbonStyleLoose | RibbonStyleThreeRow, ///< 宽松结构3行模式
RibbonStyleCompactThreeRow = RibbonStyleCompact | RibbonStyleThreeRow, ///< 紧凑结构3行模式
RibbonStyleLooseTwoRow = RibbonStyleLoose | RibbonStyleTwoRow, ///< 宽松结构2行模式
RibbonStyleCompactTwoRow = RibbonStyleCompact | RibbonStyleTwoRow ///< 紧凑结构2行模式
};
Q_ENUM(RibbonStyleFlag)
Q_DECLARE_FLAGS(RibbonStyles, RibbonStyleFlag)
Q_FLAG(RibbonStyles)
/**
* @brief 定义当前ribbon 的状态
*/
enum RibbonMode
{
MinimumRibbonMode, ///< 缩小模式
NormalRibbonMode ///< 正常模式
};
Q_ENUM(RibbonMode)
using FpCategoryIterate = std::function< bool(SARibbonCategory*) >;
using FpPannelIterate = SARibbonCategory::FpPannelIterate;
public:
// 判断RibbonStyle是否为2行模式
static bool isTwoRowStyle(RibbonStyles s);
static bool isThreeRowStyle(RibbonStyles s);
// 判断是否是office样式
static bool isLooseStyle(RibbonStyles s);
static bool isCompactStyle(RibbonStyles s);
// 获取版本信息
static QString versionString();
// 获取默认的上下文标签颜色列表
static QList< QColor > defaultContextCategoryColorList();
//
static void initHighDpi();
public:
// 构造函数
SARibbonBar(QWidget* parent = nullptr);
~SARibbonBar() Q_DECL_OVERRIDE;
// 获取applicationButton
QAbstractButton* applicationButton();
// 设置applicationButton
void setApplicationButton(QAbstractButton* btn);
// 获取tabbar
SARibbonTabBar* ribbonTabBar();
// 添加一个标签
SARibbonCategory* addCategoryPage(const QString& title);
void addCategoryPage(SARibbonCategory* category);
// 为了支持Qt designer,添加的一个重载函数
Q_INVOKABLE void addCategoryPage(QWidget* category);
// 添加一个categorycategory的位置在index如果当前category数量少于index将插入到最后
SARibbonCategory* insertCategoryPage(const QString& title, int index);
void insertCategoryPage(SARibbonCategory* category, int index);
// 通过名字查找Category
SARibbonCategory* categoryByName(const QString& title) const;
// 通过ObjectName查找Category
SARibbonCategory* categoryByObjectName(const QString& objname) const;
// 通过索引找到category如果超过索引范围会返回nullptr
SARibbonCategory* categoryByIndex(int index) const;
// 隐藏category,并不会删除或者取走,只是隐藏
void hideCategory(SARibbonCategory* category);
// 显示被隐藏的category
void showCategory(SARibbonCategory* category);
// 判断这个category是否在显示状态也就是tabbar有这个category
bool isCategoryVisible(const SARibbonCategory* c) const;
// 获取category的索引
int categoryIndex(const SARibbonCategory* c) const;
// 移动一个Category从from index到to index
void moveCategory(int from, int to);
// 获取当前显示的所有的SARibbonCategory包含未显示的SARibbonContextCategory的SARibbonCategory也一并返回
QList< SARibbonCategory* > categoryPages(bool getAll = true) const;
// 移除SARibbonCategory
void removeCategory(SARibbonCategory* category);
// 添加一个上下文标签
SARibbonContextCategory* addContextCategory(const QString& title,
const QColor& color = QColor(),
const QVariant& id = QVariant());
void addContextCategory(SARibbonContextCategory* context);
// 显示一个上下文标签
void showContextCategory(SARibbonContextCategory* context);
// 隐藏一个上下文标签
void hideContextCategory(SARibbonContextCategory* context);
// 判断上下文是否是在显示状态
bool isContextCategoryVisible(SARibbonContextCategory* context);
// 设置上下文标签的显示或隐藏
void setContextCategoryVisible(SARibbonContextCategory* context, bool visible);
// 获取所有的上下文标签
QList< SARibbonContextCategory* > contextCategoryList() const;
// 移除ContextCategory
void destroyContextCategory(SARibbonContextCategory* context);
// 设置为隐藏模式
void setMinimumMode(bool isHide);
// 当前Ribbon是否是隐藏模式
bool isMinimumMode() const;
// 设置显示隐藏ribbon按钮
void showMinimumModeButton(bool isShow = true);
// 是否显示隐藏ribbon按钮
bool haveShowMinimumModeButton() const;
// 隐藏ribbon对应的action
QAction* minimumModeAction() const;
// 当前的模式
RibbonMode currentRibbonState() const;
// ribbon tab的高度
int tabBarHeight() const;
void setTabBarHeight(int h, bool resizeByNow = true);
// 标题栏的高度
int titleBarHeight() const;
void setTitleBarHeight(int h, bool resizeByNow = true);
// category的高度
int categoryHeight() const;
void setCategoryHeight(int h, bool resizeByNow = true);
// 获取正常模式下的mainBar的高度
int normalModeMainBarHeight() const;
// 最小模式下的MainBar高度
int minimumModeMainBarHeight() const;
// 激活tabbar右边的按钮群
SARibbonButtonGroupWidget* activeRightButtonGroup();
// 右侧按钮群
SARibbonButtonGroupWidget* rightButtonGroup();
// 激活QuickAccessBar
SARibbonQuickAccessBar* activeQuickAccessBar();
// 快速响应栏
SARibbonQuickAccessBar* quickAccessBar();
// 设置ribbon的风格
void setRibbonStyle(RibbonStyles v);
RibbonStyles currentRibbonStyle() const;
// 设置当前ribbon的index
void setCurrentIndex(int index);
// 返回当前的tab索引
int currentIndex();
// 确保标签显示出来
void raiseCategory(SARibbonCategory* category);
// 判断当前的行数
bool isTwoRowStyle() const;
bool isThreeRowStyle() const;
// 判断当前的样式
bool isLooseStyle() const;
bool isCompactStyle() const;
// 更新ribbon的布局数据此函数适用于一些关键性尺寸变化换起ribbon下面元素的布局,在发现刷新问题时,可以调用此函数
void updateRibbonGeometry();
// 设置pannel的模式
SARibbonPannel::PannelLayoutMode pannelLayoutMode() const;
void setPannelLayoutMode(SARibbonPannel::PannelLayoutMode m);
// 设置tab在title上面这样可以省略title区域
void setTabOnTitle(bool on);
bool isTabOnTitle() const;
// tabbar 底部会绘制一条线条,此接口定义线条颜色
void setTabBarBaseLineColor(const QColor& clr);
QColor tabBarBaseLineColor() const;
// 设置标题颜色,如果不设置标题颜色默认是SARibbonBar的qss的color属性
void setWindowTitleTextColor(const QColor& clr);
QColor windowTitleTextColor() const;
// 设置标题的对齐方式
void setWindowTitleAligment(Qt::Alignment al);
Qt::Alignment windowTitleAligment() const;
// 设置按钮允许换行,注意图标大小是由文字决定的,两行文字会让图标变小,如果想图标变大,文字不换行是最好的
void setEnableWordWrap(bool on);
bool isEnableWordWrap() const;
// 设置pannel的标题栏高度
int pannelTitleHeight() const;
void setPannelTitleHeight(int h);
// 设置pannel是否显示标题栏
bool isEnableShowPannelTitle() const;
void setEnableShowPannelTitle(bool on);
// 获取SARibbonStackedWidget谨慎使用此函数
SARibbonStackedWidget* ribbonStackedWidget();
// 设置是否显示标题
void setTitleVisible(bool on = false);
bool isTitleVisible() const;
// 上下文标签的颜色列表,上下文标签显示的时候,会从颜色列表中取颜色进行标签的渲染
void setContextCategoryColorList(const QList< QColor >& cls);
QList< QColor > contextCategoryColorList() const;
// 设置context category 标题的文字颜色
void setContextCategoryTitleTextColor(const QColor& clr);
QColor contextCategoryTitleTextColor() const;
// 设置ribbon的对齐方式
void setRibbonAlignment(SARibbonAlignment al);
SARibbonAlignment ribbonAlignment() const;
// 此函数会遍历SARibbonBar下的所有Category执行函数指针(bool(SARibbonCategory*))函数指针返回false则停止迭代
bool iterate(FpCategoryIterate fp);
// 此函数会遍历SARibbonBar下的所有Category,并迭代所有的pannel执行函数指针(bool(SARibbonPannel*))函数指针返回false则停止迭代
bool iterate(FpPannelIterate fp);
// 设置边角widget可见性对于mdi窗口会出现TopLeftCorner和TopRightCorner两个corner widget
void setCornerWidgetVisible(bool on, Qt::Corner c = Qt::TopLeftCorner);
signals:
/**
@brief 应用按钮点击响应 - 左上角的按钮,通过关联此信号触发应用按钮点击的效果
例如想点击按钮后弹出一个全屏的窗口如office这些
*/
void applicationButtonClicked();
/**
@brief 标签页变化触发的信号
@param index
*/
void currentRibbonTabChanged(int index);
/**
@brief ribbon的状态发生了变化后触发此信号
@param nowState 变更之后的ribbon状态
*/
void ribbonModeChanged(SARibbonBar::RibbonMode nowState);
/**
@brief ribbon的状态发生了变化后触发此信号
@param nowStyle 变更之后的ribbon样式
*/
void ribbonStyleChanged(SARibbonBar::RibbonStyles nowStyle);
/**
@brief 标题栏高度发生了变化的信号
@param oldHeight
@param newHeight
*/
void titleBarHeightChanged(int oldHeight, int newHeight);
/**
* @brief 参考QToolBar::actionTriggered的信号
* @param action
*/
void actionTriggered(QAction* action);
protected:
bool eventFilter(QObject* obj, QEvent* e) override;
// 根据情况重置tabbar的宽度主要针对wps模式
int calcMinTabBarWidth() const;
// 更新
void updateCategoryTitleToTabName();
// 告知WindowButtonGroup的尺寸
void setWindowButtonGroupSize(const QSize& s);
protected slots:
void onWindowTitleChanged(const QString& title);
void onWindowIconChanged(const QIcon& i);
void onCategoryWindowTitleChanged(const QString& title);
void onStackWidgetHided();
virtual void onCurrentRibbonTabChanged(int index);
virtual void onCurrentRibbonTabClicked(int index);
virtual void onCurrentRibbonTabDoubleClicked(int index);
void onContextsCategoryPageAdded(SARibbonCategory* category);
void onContextsCategoryCategoryNameChanged(SARibbonCategory* category, const QString& title);
void onTabMoved(int from, int to);
private:
int tabIndex(SARibbonCategory* obj);
void resizeAll();
void resizeInLooseStyle();
void resizeInCompactStyle();
void paintInLooseStyle();
void paintInCompactStyle();
void resizeStackedContainerWidget();
// 刷新所有ContextCategoryManagerData这个在单独一个Category删除时调用
void updateContextCategoryManagerData();
void synchronousCategoryData(bool autoUpdate = true);
protected:
virtual void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE;
virtual void resizeEvent(QResizeEvent* e) Q_DECL_OVERRIDE;
virtual void moveEvent(QMoveEvent* e) Q_DECL_OVERRIDE;
virtual void changeEvent(QEvent* e) Q_DECL_OVERRIDE;
virtual bool event(QEvent* e) Q_DECL_OVERRIDE;
virtual void paintTabbarBaseLine(QPainter& painter);
virtual void paintWindowTitle(QPainter& painter, const QString& title, const QRect& titleRegion);
virtual void paintContextCategoryTab(QPainter& painter, const QString& title, const QRect& contextRect, const QColor& color);
#if SA_DEBUG_PRINT_SARIBBONBAR
SA_RIBBON_EXPORT friend QDebug operator<<(QDebug debug, const SARibbonBar& ribbon);
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SARibbonBar::RibbonStyles)
#endif // SARIBBONBAR_H