Menu.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #ifndef MENU_H
  2. #define MENU_H
  3. #include <QMenu>
  4. #include <QListWidget>
  5. #include <QProxyStyle>
  6. #include <QHBoxLayout>
  7. #include <QPropertyAnimation>
  8. #include <QGraphicsDropShadowEffect>
  9. #include <QPair>
  10. #include <QLineEdit>
  11. #include <QTextEdit>
  12. #include <QPlainTextEdit>
  13. #include <QEventLoop>
  14. class SmoothScroll;
  15. class MenuActionListWidget;
  16. class SubMenuItemWidget;
  17. class CustomMenuStyle : public QProxyStyle
  18. {
  19. Q_OBJECT
  20. public:
  21. explicit CustomMenuStyle(int iconSize = 14);
  22. private:
  23. int m_iconSize;
  24. // QStyle interface
  25. public:
  26. virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override;
  27. };
  28. class DWMMenu : public QMenu
  29. {
  30. Q_OBJECT
  31. public:
  32. explicit DWMMenu(const QString &title = "", QWidget *parent = nullptr);
  33. // QObject interface
  34. public:
  35. virtual bool event(QEvent *event) override;
  36. private:
  37. QScopedPointer<CustomMenuStyle> m_customMenuStyle;
  38. };
  39. class MenuSeparator : public QWidget
  40. {
  41. Q_OBJECT
  42. public:
  43. explicit MenuSeparator(QWidget *parent = nullptr);
  44. // QWidget interface
  45. protected:
  46. virtual void paintEvent(QPaintEvent *event) override;
  47. };
  48. class RoundMenu : public QWidget
  49. {
  50. Q_OBJECT
  51. public:
  52. explicit RoundMenu(const QString &title = "", QWidget *parent = nullptr);
  53. void setShadowEffect(qreal blurRadius = 30, const QPointF &offset = QPoint(0, 8),
  54. const QColor &color = QColor(0, 0, 0, 30));
  55. void setItemHeight(int itemHeight);
  56. void adjustSize();
  57. QString title() const;
  58. QIcon icon() const;
  59. void setIcon(const QIcon &icon);
  60. void clear();
  61. void removeAction(QAction *action);
  62. void addAction(QAction *const action);
  63. void insertAction(QAction *const before, QAction *const action);
  64. void addActions(const QList<QAction *> &actions);
  65. void insertActions(QAction *const before, const QList<QAction *> &actions);
  66. void setDefaultAction(QAction *const action);
  67. void addMenu(RoundMenu *const menu);
  68. void insertMenu(QAction *const before, RoundMenu *const menu);
  69. RoundMenu *parentMenu() const;
  70. QList<QAction *> menuActions() const;
  71. MenuActionListWidget *view() const;
  72. void addSeparator();
  73. virtual void exec(const QPoint &pos, bool ani = true);
  74. protected:
  75. void setParentMenu(RoundMenu *parent, QListWidgetItem *item);
  76. QListWidgetItem *createActionItem(QAction *const action, QAction *const before = nullptr);
  77. bool hasItemIcon();
  78. QIcon createItemIcon(QAction *const action);
  79. QIcon createItemIcon(RoundMenu *const menu);
  80. QPair<QListWidgetItem *, SubMenuItemWidget *> createSubMenuItem(RoundMenu *const menu);
  81. void hideMenu(bool hideBySystem = false);
  82. void closeParentMenu();
  83. void mouseMoveEvent(QMouseEvent *event) override;
  84. void closeEvent(QCloseEvent *event) override;
  85. void hideEvent(QHideEvent *event) override;
  86. private:
  87. void initWidgets();
  88. protected slots:
  89. void onShowMenuTimeOut();
  90. virtual void onItemClicked(QListWidgetItem *item);
  91. void onItemEntered(QListWidgetItem *item);
  92. void onSlideValueChanged(const QVariant &value);
  93. void onActionChanged();
  94. void showSubMenu(QListWidgetItem *const item);
  95. signals:
  96. void closedSignal();
  97. private:
  98. QString m_title;
  99. QIcon m_icon;
  100. QList<QAction *> m_actions;
  101. QList<RoundMenu *> m_subMenus;
  102. bool m_isSubMenu;
  103. RoundMenu *m_parentMenu;
  104. QListWidgetItem *m_menuItem;
  105. QListWidgetItem *m_lastHoverItem;
  106. QListWidgetItem *m_lastHoverSubMenuItem;
  107. bool m_isHideBySystem;
  108. int m_itemHeight;
  109. QHBoxLayout *m_hBoxLayout;
  110. MenuActionListWidget *m_view;
  111. QPropertyAnimation *m_ani;
  112. QTimer *m_timer;
  113. QGraphicsDropShadowEffect *m_shadowEffect;
  114. QEventLoop *m_eventLoop; //模态堵塞使用
  115. };
  116. Q_DECLARE_METATYPE(QListWidgetItem *)
  117. Q_DECLARE_METATYPE(QAction *)
  118. Q_DECLARE_METATYPE(RoundMenu *)
  119. class SubMenuItemWidget : public QWidget
  120. {
  121. Q_OBJECT
  122. public:
  123. explicit SubMenuItemWidget(QMenu *menu, QListWidgetItem *item, QWidget *parent = nullptr);
  124. explicit SubMenuItemWidget(RoundMenu *menu, QListWidgetItem *item, QWidget *parent = nullptr);
  125. // QWidget interface
  126. RoundMenu *roundMenu() const;
  127. protected:
  128. virtual void enterEvent(QEvent *event) override;
  129. virtual void paintEvent(QPaintEvent *event) override;
  130. signals:
  131. void showMenuSig(QListWidgetItem *const);
  132. private:
  133. QMenu *m_menu;
  134. RoundMenu *m_roundMenu;
  135. QListWidgetItem *m_item;
  136. };
  137. class MenuActionListWidget : public QListWidget
  138. {
  139. Q_OBJECT
  140. public:
  141. explicit MenuActionListWidget(QWidget *parent = nullptr);
  142. void insertItem(int row, QListWidgetItem *item);
  143. void addItem(QListWidgetItem *item);
  144. QListWidgetItem *takeItem(int row);
  145. void adjustSize();
  146. void setItemHeight(int height);
  147. QMargins viewportMargins() { return QListWidget::viewportMargins(); }
  148. // QWidget interface
  149. protected:
  150. virtual void wheelEvent(QWheelEvent *event) override;
  151. private:
  152. QScopedPointer<SmoothScroll> m_smoothScroll;
  153. };
  154. class EditMenu : public RoundMenu
  155. {
  156. Q_OBJECT
  157. public:
  158. explicit EditMenu(QWidget *parent = nullptr);
  159. void createActions();
  160. void exec(const QPoint &pos, bool ani = true) override;
  161. QAction *cutAct;
  162. QAction *copyAct;
  163. QAction *pasteAct;
  164. QAction *cancelAct;
  165. QAction *selectAllAct;
  166. QList<QAction *> actionList;
  167. protected:
  168. virtual QString parentText() = 0;
  169. virtual QString parentSelectedText() = 0;
  170. };
  171. class LineEditMenu : public EditMenu
  172. {
  173. Q_OBJECT
  174. public:
  175. explicit LineEditMenu(QLineEdit *parent);
  176. // RoundMenu interface
  177. protected slots:
  178. void onItemClicked(QListWidgetItem *item) override;
  179. // EditMenu interface
  180. protected:
  181. QString parentText() override;
  182. QString parentSelectedText() override;
  183. private:
  184. int m_selectionStart;
  185. int m_selectionLength;
  186. };
  187. class TextEditMenu : public EditMenu
  188. {
  189. Q_OBJECT
  190. public:
  191. explicit TextEditMenu(QTextEdit *parent);
  192. explicit TextEditMenu(QPlainTextEdit *parent);
  193. // RoundMenu interface
  194. protected slots:
  195. void onItemClicked(QListWidgetItem *item) override;
  196. // EditMenu interface
  197. protected:
  198. QString parentText() override;
  199. QString parentSelectedText() override;
  200. private:
  201. int m_selectionStart;
  202. int m_selectionLength;
  203. QTextEdit *m_textEdit;
  204. QPlainTextEdit *m_plainTextEdit;
  205. };
  206. #endif // MENU_H