#ifndef QSR_RIBBON_CORE_H #define QSR_RIBBON_CORE_H #include #include #include #include #include #include #include #include /* * 当前的程序主要是运行在windows系统下, 如果运行在Linux下还需要进行优化,比如主界面的外框等 */ // 从大于0的开始, RIBBON开始的是控件,三级的归属于二级 //(暂时还没有使用) enum RIBBON_OBJECT_TYPE // RIBBON 对象 { RIBBON_OBJECTITEM = 0, RIBBON_TITLEBAR_QuickAccessBar, // 标题栏上左侧的 快捷图标 RIBBON_TITLEBAR_Title, // 标题栏的 标题 RIBBON_TITLEBAR_UserInfo, // 标题栏上的 用户信息 RIBBON_TITLEBAR_StanderdButton, // 标题栏上的 右侧按钮 RIBBON_TITLEBAR, // 以上是标题栏的内容 RIBBON_MENUBAR_WidgetActionLeft, // 比如word中的“文件”按钮 RIBBON_MENUBAR_WidgetActionRight, // 右侧的按钮 RIBBON_MENUBAR, // 以上是菜单栏的内容 RIBBON_TOOLBAR_GroupWidget, // 工具栏的控件容器(如 word中的“段落”为一组) RIBBON_TOOLBAR_IconWidget, // 大图标缩略图 RIBBON_TOOLBAR_Saperator, // 工具栏控件容器中的分隔线 RIBBON_TOOLBAR,// 以上是工具栏的内容 RIBBON_CONTRAL_Control // 具体的控件 }; #include /** @brief Ribbon操作. * @details 一个操作对应一个图标,或者控件 */ typedef QWidget ribbonAction; /** @brief Ribbon Widget 的基类. * @details 为了实现Qss对QWidget的重绘 */ class RobbonWidget :public QWidget { public: RobbonWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~RobbonWidget(); protected: virtual void paintEvent(QPaintEvent *event); private: }; ////////////////////////////////////////////////////////////////////////// // 需要自定义一套按钮,用来显示/隐藏 图标、文字, 参考之前实现的那个按钮的代码 /** @brief RibbonControlBase 控件基类. * @details */ class RibbonControlBase { public: RibbonControlBase(); ~RibbonControlBase(); /** @brief 设置控件在GroupWidget中的位置,有两套位置可以设置. * @details 如果只有一种布局则不需要设置index参数. */ void setGroupPos(QPoint tPos, int index = -1); QPoint groupPos(int index); virtual void setText(QString &text) {}; virtual void setIcon(const QIcon &icon) {}; virtual void setEnabled(bool &tEnabled) {}; private: QPoint m_pos0, m_pos1; }; /** @brief RibbonPushButton 普通Ribbon按钮类. * @details */ class RibbonToolButton : public QPushButton, public RibbonControlBase { Q_OBJECT public: RibbonToolButton(QWidget *parent = Q_NULLPTR); RibbonToolButton(const QString &text, QWidget *parent = Q_NULLPTR); RibbonToolButton(const QIcon &icon, const QString &text, QWidget *parent = Q_NULLPTR); ~RibbonToolButton(); void setTxtVisible(bool tVal); bool txtVisible(); /** @brief 对齐方式. */ void setAlignment(Qt::Alignment flag); /** @brief 设置Action. //放弃使用: 不再接受从外部赋值 */ //void setAction(QAction* tAction); /** @brief 获取Action. 用于从Ribbon风格切换到传统样式的菜单工具栏等 */ QAction* getAction(); virtual void setText(QString &text); virtual void setIcon(const QIcon &icon); virtual void setEnabled(bool &tEnabled); private: QString m_text; bool m_txtVisible; /** @brief Action指针,从外部指定. */ QAction* m_action; // private: // RIBBON_OBJECT_TYPE m_objType; }; /** @brief RibbonPushButton 大的Ribbon按钮类. * @details */ class RibbonToolButtonBig : public RobbonWidget, public RibbonControlBase { Q_OBJECT public: RibbonToolButtonBig(const QIcon &icon, const QString &text, QWidget *parent = Q_NULLPTR); ~RibbonToolButtonBig(); QPushButton* pushButton() const; QLabel* label() const; void setExtentIconVisible(bool tVal); virtual void setText(QString &text) {}; virtual void setIcon(const QIcon &icon){}; virtual void setEnabled(bool &tEnabled){}; signals: void triggered(bool checked = false); private: QPushButton* m_pushButton; QLabel* m_label, *m_label_extent; }; // class ribbonAction: public QWidget // { // Q_OBJECT // public: // ribbonAction(); // ~ribbonAction() {}; // // private: // // // }; //基类 // class QsrRibbonObject // { // public: // QsrRibbonObject() {}; // ~QsrRibbonObject() {}; // }; class QsrRibbonQuickAccessToolBar : /*public QsrRibbonObject,*/ public QToolBar { Q_OBJECT public: QsrRibbonQuickAccessToolBar() ; ~QsrRibbonQuickAccessToolBar() {}; }; /** @brief 标题栏. * @details 标题栏的组成(从左到右): 快捷工具栏,标题控件,用户信息控件,系统按钮(放置系统按钮:设置、最小化、最大化、关闭) */ class QsrRibbonTitleBar : /*public QsrRibbonObject ,*/ public RobbonWidget { Q_OBJECT public: QsrRibbonTitleBar(); ~QsrRibbonTitleBar(); /** @brief 设置窗口标题. * * @details 设置窗口标题. * @param title 窗口的标题. * @return . */ void setTitle(QString title); QString getTitle(); /** @brief 设置工具条的文字. */ void setToolsText(QString txt); void addQuickAction(QAction *action); void addSysAction(QAction* action); void setUserInfo(QString txt); private: QLabel* m_titleLable1, m_ToolsLabel, m_titleLable2; QLabel* m_userInfoLabel; QsrRibbonQuickAccessToolBar* m_quickAccessToolBar, *m_systemButton; }; /** @brief Ribbon 操作组. * @details Ribbon 操作组 */ #include #include class QtbGroupWidget : public RobbonWidget { Q_OBJECT public: QtbGroupWidget(); ~QtbGroupWidget(); void setTitle(QString tTitle); void addAction(ribbonAction* rAct, int row, int col, int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = Qt::Alignment()); void addAction(RibbonToolButton* rAct, int row, int col, int rowSpan /*= 1*/, int columnSpan /*= 1*/, Qt::Alignment alignment /*= Qt::Alignment()*/); QActionGroup* getActionGroup() const; protected: virtual void paintEvent(QPaintEvent *event); private: QGridLayout* m_gridLayout; QLabel* m_groupTitleLabel; QActionGroup* m_actionGroup; }; /** @brief Ribbon菜单栏. * @details Ribbon菜单栏 */ #include #include #include #include #include class QtbMenuBar : /*public QsrRibbonObject ,*/ public RobbonWidget { Q_OBJECT public: QtbMenuBar(); ~QtbMenuBar(); /** @brief 增加操作按钮. */ void addAction(ribbonAction* tAction,int tIndex); /** @brief 增加菜单. menuName是唯一的,也是显示的 */ void addMenu(QString menuName); /** @brief 增加扩展型菜单. menuName是全局唯一的,showName是显示的可以重复 */ // void addExtendedMenu(QString menuName, QString showName); void setMenuVisible(QString menuName, bool tIsVisible); bool isMenuVisible(QString menuName); QtbGroupWidget* addGroup(QString menuName, QString txtGroupTitle); void menuReady(QString menuName); void setExtentBtnIcon(QIcon icoExtent, QIcon icoHide); bool isToolBarVisible(); public slots: void setToolBarVisible(bool tVal); private slots: /** @brief Ribbon工具栏折叠/展开按钮的操作. */ void onExtentToggled(); void onCurrentTabChenged(int index); protected: virtual void enterEvent(QEvent *event); virtual void leaveEvent(QEvent *event); private: /** @brief 菜单栏的TabBar. */ QTabBar* m_menuTabBar; QTabBar* m_ExtentedMenuTabBar; /** @brief Ribbon菜单的主layout. */ QHBoxLayout* m_layout; /** @brief Ribbon菜单的主layout. */ QMap m_StaWidMap; /* 暂时不提供扩展型的可变菜单*/ // QHBoxLayout* m_layoutExtented; // /** @brief Ribbon扩展菜单的按钮. */ // QMap m_extentedBtnMap; // QWidget* m_extentedWidget; QStackedWidget* m_toolBarStackedWid; /** @brief 折叠按钮. */ RibbonToolButton* m_extentBtn; bool m_toolBarVisible; QIcon m_icoExtent, m_icoHide; }; /** @brief Ribbon工具栏. * @details Ribbon工具栏. */ class QtbToolBar : /*public QsrRibbonObject ,*/ public QTabWidget { Q_OBJECT public: QtbToolBar(); ~QtbToolBar(); void addMenu(QString txt); private: // QTabBar m_menuTabBar; // QHBoxLayout m_layout; // QMap m_menuLabelMap; // QTabWidget* m_toolTabWidget; }; /** @brief 主窗口. * @details */ #include class QsfWorkWindow; class QDockWidget; //#include "SgfParamManager.h" class QtbMainWindow : public RobbonWidget //, public SgfParamManager { Q_OBJECT public: QtbMainWindow(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~QtbMainWindow(); QsrRibbonTitleBar* titleBar(); QtbMenuBar* menuBar(); /** @brief 创建DockWidget. */ QDockWidget* createDockWidget(QString title, QString name, Qt::DockWidgetArea area); /** @brief 创建工作页Widget. */ QWidget* createWorkWidget(QString title, QString name); /** @brief 添加已有的widget作为工作页Widget. */ void addWorkWidget(QWidget* tWidget); private: QsrRibbonTitleBar* m_titleBar; QtbMenuBar* m_menuBar; protected: /** @brief 标题范围. */ QRect m_titleRect; /** @brief 工作窗口. */ QsfWorkWindow* m_workWindow; /** @brief 鼠标上一次的位置. */ QPoint oldMousePos; /** @brief 鼠标单击. */ void mousePressEvent(QMouseEvent *event); /** @brief 鼠标上双击. */ void mouseDoubleClickEvent(QMouseEvent * event); /** @brief 鼠标拖动. */ void mouseMoveEvent(QMouseEvent *event); virtual void resizeEvent(QResizeEvent *event); virtual void paintEvent(QPaintEvent *event); public slots: void onSkin(); }; /** @brief 主窗口借助dwmapi实现在windows下的拖动 * @details Linux下的暂时没有做实现。次出应当用宏来统一windows和linux */ #include #include class NativeEventFilter : public QAbstractNativeEventFilter { public: bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) Q_DECL_OVERRIDE { #ifdef Q_OS_WIN if (eventType != "windows_generic_MSG") return false; MSG* msg = static_cast(message); QWidget* widget0 = QWidget::find(reinterpret_cast(msg->hwnd)); if (widget0 == NULL) return false; QtbMainWindow* widget = static_cast(widget0); if (!widget) return false; if (widget->isMaximized()) return false; switch (msg->message) { // case WM_NCCALCSIZE: { // 如果处理该消息,dock窗口或子窗口会有问题 // *result = 0; // return true; // } case WM_NCHITTEST: { const LONG borderWidth = 9; RECT winrect; GetWindowRect(msg->hwnd, &winrect); long x = GET_X_LPARAM(msg->lParam); long y = GET_Y_LPARAM(msg->lParam); // bottom left if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMLEFT; return true; } // bottom right if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOMRIGHT; return true; } // top left if (x >= winrect.left && x < winrect.left + borderWidth && y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPLEFT; return true; } // top right if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOPRIGHT; return true; } // left if (x >= winrect.left && x < winrect.left + borderWidth) { *result = HTLEFT; return true; } // right if (x < winrect.right && x >= winrect.right - borderWidth) { *result = HTRIGHT; return true; } // bottom if (y < winrect.bottom && y >= winrect.bottom - borderWidth) { *result = HTBOTTOM; return true; } // top if (y >= winrect.top && y < winrect.top + borderWidth) { *result = HTTOP; return true; } return false; } default: break; } return false; #else return false; #endif } }; #endif //QSF_TITLEBAR_H