QtCanpool 3.3.0
载入中...
搜索中...
未找到
ribbonactionsmanager.cpp
浏览该文件的文档.
1
8#include "ribbonbar.h"
9
10#include <QDebug>
11#include <QHash>
12#include <QMap>
13
15
16class RibbonActionsManagerPrivate
17{
19public:
20 RibbonActionsManagerPrivate();
21 void clear();
22public:
23 QMap<int, QList<QAction *>> m_tagToActions;
24 QMap<int, QString> m_tagToName;
25 QHash<QString, QAction *> m_keyToAction;
26 QMap<QAction *, QString> m_actionToKey;
27 QMap<int, RibbonPage *> m_tagToPage;
28 int m_salt;
30};
31
32RibbonActionsManagerPrivate::RibbonActionsManagerPrivate()
33 : m_salt(0)
34{
35}
36
37void RibbonActionsManagerPrivate::clear()
38{
39 m_tagToActions.clear();
40 m_tagToName.clear();
41 m_keyToAction.clear();
42 m_actionToKey.clear();
43 m_tagToPage.clear();
44 m_salt = 0;
45}
46
47RibbonActionsManager::RibbonActionsManager(RibbonBar *bar)
48 : QObject(bar)
49{
52}
53
58
65void RibbonActionsManager::setTagName(int tag, const QString &name)
66{
68 d->m_tagToName[tag] = name;
69}
70
76QString RibbonActionsManager::tagName(int tag) const
77{
78 Q_D(const RibbonActionsManager);
79 return d->m_tagToName.value(tag, "");
80}
81
88{
90 QList<QAction *> willRemoveActs = actions(tag);
91
92 // 开始移除
93 d->m_tagToActions.remove(tag);
94 d->m_tagToName.remove(tag);
95
96 // 开始查找需要移出总表的action
97 QList<QAction *> needRemoveActs;
98 QList<QAction *> remainingActs;
99
100 for (auto i = d->m_tagToActions.begin(); i != d->m_tagToActions.end(); ++i) {
101 remainingActs += i.value();
102 }
103 for (QAction *a : willRemoveActs) {
104 if (!remainingActs.contains(a)) {
105 needRemoveActs.append(a);
106 }
107 }
108 // 从总表移除action
109 for (QAction *a : needRemoveActs) {
110 auto i = d->m_actionToKey.find(a);
111 if (i != d->m_actionToKey.end()) {
112 d->m_keyToAction.remove(i.value());
113 d->m_actionToKey.erase(i);
114 }
115 }
116}
117
130bool RibbonActionsManager::registerAction(QAction *act, int tag, const QString &key, bool enableEmit)
131{
133 if (Q_NULLPTR == act) {
134 return false;
135 }
136 QString k = key;
137
138 if (k.isEmpty()) {
139 k = QString("id_%1_%2").arg(d->m_salt++).arg(act->objectName());
140 }
141 if (d->m_keyToAction.contains(k)) {
142 qWarning()
143 << "key: " << k
144 << " have been exist,you can set key in an unique value when use RibbonActionsManager::registerAction";
145 return false;
146 }
147 d->m_keyToAction[k] = act;
148 d->m_actionToKey[act] = k;
149 // 记录tag 对 action
150 bool isneedemit = !(d->m_tagToActions.contains(tag)); // 记录是否需要发射信号
151
152 d->m_tagToActions[tag].append(act);
153 // 绑定槽
154 connect(act, &QObject::destroyed, this, &RibbonActionsManager::onActionDestroyed);
155 if (isneedemit && enableEmit) {
156 // 说明新增tag
157 Q_EMIT actionTagChanged(tag, false);
158 }
159 return true;
160}
161
171void RibbonActionsManager::unregisterAction(QAction *act, bool enableEmit)
172{
173 if (Q_NULLPTR == act) {
174 return;
175 }
176 // 绑定槽
177 disconnect(act, &QObject::destroyed, this, &RibbonActionsManager::onActionDestroyed);
178 removeAction(act, enableEmit);
179}
180
188void RibbonActionsManager::removeAction(QAction *act, bool enableEmit)
189{
191 QList<int> deletedTags; // 记录删除的tag,用于触发actionTagChanged
192 QMap<int, QList<QAction *>> tagToActions;
193
194 if (!d->m_actionToKey.contains(act)) {
195 return;
196 }
197
198 for (auto i = d->m_tagToActions.begin(); i != d->m_tagToActions.end(); ++i) {
199 // 把不是act的内容转移到tagToActions中,之后再和d里的替换
200 auto tmpi = tagToActions.insert(i.key(), QList<QAction *>());
201 int count = 0;
202 for (int j = 0; j < i.value().size(); ++j) {
203 QAction *tmpAct = i.value()[j];
204 if (tmpAct != act) {
205 tmpi.value().append(tmpAct);
206 ++count;
207 }
208 }
209 if (0 == count) {
210 // 说明这个tag没有内容
211 tagToActions.erase(tmpi);
212 deletedTags.append(i.key());
213 }
214 }
215 // 删除keyToAction
216 QString key = d->m_actionToKey.value(act);
217 d->m_actionToKey.remove(act);
218 d->m_keyToAction.remove(key);
219
220 // 置换
221 d->m_tagToActions.swap(tagToActions);
222 // 发射信号
223 if (enableEmit) {
224 for (int delTag : deletedTags) {
225 Q_EMIT actionTagChanged(delTag, true);
226 }
227 }
228}
229
235QList<QAction *> RibbonActionsManager::actions(int tag) const
236{
237 Q_D(const RibbonActionsManager);
238 return d->m_tagToActions.value(tag);
239}
240
246{
247 Q_D(const RibbonActionsManager);
248 return d->m_tagToActions.keys();
249}
250
256QAction *RibbonActionsManager::action(const QString &key) const
257{
258 Q_D(const RibbonActionsManager);
259 return d->m_keyToAction.value(key, Q_NULLPTR);
260}
261
267QString RibbonActionsManager::key(QAction *act) const
268{
269 Q_D(const RibbonActionsManager);
270 return d->m_actionToKey.value(act, QString());
271}
272
278{
279 Q_D(const RibbonActionsManager);
280 return d->m_keyToAction.size();
281}
282
287QList<QAction *> RibbonActionsManager::allActions() const
288{
289 Q_D(const RibbonActionsManager);
290 return d->m_keyToAction.values();
291}
292
308{
310 QMap<int, RibbonPage *> res;
311 if (Q_NULLPTR == bar) {
312 return res;
313 }
314 // 先遍历RibbonBar下的所有子对象,把所有action找到
315 QSet<QAction *> ribbonBarActions;
316
317 for (QObject *o : bar->children()) {
318 if (QAction *a = qobject_cast<QAction *>(o)) {
319 if (!a->objectName().isEmpty()) {
320 ribbonBarActions.insert(a);
321 }
322 }
323 }
324
325 QSet<QAction *> pageActions;
326 QList<RibbonPage *> pages = bar->pages();
328
329 for (RibbonPage *page : pages) {
330 QList<RibbonGroup *> groups = page->groupList();
331 for (RibbonGroup *group : groups) {
332 pageActions += autoRegisterWidgetActions(group, tag, false);
333 }
334 setTagName(tag, page->windowTitle());
335 res[tag] = page;
336 ++tag;
337 }
338 // 找到不在功能区的actions
339 QSet<QAction *> notInPageActions = ribbonBarActions - pageActions;
340
341 for (QAction *a : notInPageActions) {
342 if (!a->objectName().isEmpty()) {
343 registerAction(a, NotInRibbonPageTag, a->objectName(), false);
344 }
345 }
346 if (notInPageActions.size() > 0) {
347 setTagName(NotInRibbonPageTag, tr("not in ribbon"));
348 }
349 for (auto i = res.begin(); i != res.end(); ++i) {
350 connect(i.value(), &RibbonPage::windowTitleChanged, this, &RibbonActionsManager::onPageTitleChanged);
351 }
352 d->m_tagToPage = res;
353 return res;
354}
355
363QSet<QAction *> RibbonActionsManager::autoRegisterWidgetActions(QWidget *w, int tag, bool enableEmit)
364{
365 QSet<QAction *> res;
366 QList<QAction *> was = w->actions();
367
368 for (QAction *a : was) {
369 if (res.contains(a) || a->objectName().isEmpty()) {
370 // 重复内容不重复加入,没有object name不加入
371 continue;
372 }
373 if (registerAction(a, tag, a->objectName(), enableEmit)) {
374 res.insert(a);
375 }
376 }
377 return res;
378}
379
385QList<QAction *> RibbonActionsManager::search(const QString &text)
386{
387 Q_D(const RibbonActionsManager);
388 QList<QAction *> res;
389
390 if (text.isEmpty()) {
391 return res;
392 }
393 QStringList kws = text.split(" ");
394
395 if (kws.isEmpty()) {
396 kws.append(text);
397 }
398
399 for (const QString &k : kws) {
400 for (auto i = d->m_actionToKey.begin(); i != d->m_actionToKey.end(); ++i) {
401 if (i.key()->text().contains(k, Qt::CaseInsensitive)) {
402 res.append(i.key());
403 }
404 }
405 }
406 return res;
407}
408
410{
412 d->clear();
413}
414
416{
417 return qobject_cast<RibbonBar *>(parent());
418}
419
425{
427 for (auto i = d->m_actionToKey.begin(); i != d->m_actionToKey.end(); ++i) {
429 }
430}
431
438{
439 QAction *act = static_cast<QAction *>(o);
440
441 removeAction(act, false);
442}
443
449{
451 RibbonPage *page = qobject_cast<RibbonPage *>(sender());
452
453 if (Q_NULLPTR == page) {
454 return;
455 }
456 int tag = d->m_tagToPage.key(page, -1);
457
458 if (tag == -1) {
459 return;
460 }
461 setTagName(tag, title);
462}
463
467class RibbonActionsManagerModelPrivate
468{
470public:
471 RibbonActionsManagerModelPrivate();
472
473 void updateRef();
474 int count() const;
475 QAction *at(int index) const;
476 bool isNull() const;
477public:
479 int m_tag;
480 QString m_seatchText;
481 QList<QAction *> m_actions;
482};
483
484RibbonActionsManagerModelPrivate::RibbonActionsManagerModelPrivate()
485 : m_mgr(Q_NULLPTR)
486 , m_tag(RibbonActionsManager::CommonlyUsedActionTag)
487 , m_seatchText(QString())
488{
489}
490
491void RibbonActionsManagerModelPrivate::updateRef()
492{
493 if (isNull()) {
494 return;
495 }
496 if (!m_seatchText.isEmpty()) {
497 m_actions = m_mgr->search(m_seatchText);
498 } else {
499 m_actions = m_mgr->actions(m_tag);
500 }
501}
502
503int RibbonActionsManagerModelPrivate::count() const
504{
505 if (isNull()) {
506 return 0;
507 }
508 return m_actions.size();
509}
510
511QAction *RibbonActionsManagerModelPrivate::at(int index) const
512{
513 if (isNull()) {
514 return Q_NULLPTR;
515 }
516 if (index >= count()) {
517 return Q_NULLPTR;
518 }
519 return m_actions.at(index);
520}
521
522bool RibbonActionsManagerModelPrivate::isNull() const
523{
524 return (m_mgr == Q_NULLPTR);
525}
526
529
535
540
541int RibbonActionsManagerModel::rowCount(const QModelIndex &parent) const
542{
543 Q_D(const RibbonActionsManagerModel);
544 if (parent.isValid()) { // 非顶层
545 return 0;
546 }
547 // 顶层
548 return d->count();
549}
550
551QVariant RibbonActionsManagerModel::headerData(int section, Qt::Orientation orientation, int role) const
552{
553 Q_UNUSED(section);
554 if (role != Qt::DisplayRole) {
555 return QVariant();
556 }
557 if (Qt::Horizontal == orientation) {
558 return tr("action name");
559 }
560 return QVariant();
561}
562
563Qt::ItemFlags RibbonActionsManagerModel::flags(const QModelIndex &index) const
564{
565 if (!index.isValid()) {
566 return Qt::NoItemFlags;
567 }
568 return (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
569}
570
571QVariant RibbonActionsManagerModel::data(const QModelIndex &index, int role) const
572{
573 QAction *act = indexToAction(index);
574
575 if (Q_NULLPTR == act) {
576 return QVariant();
577 }
578
579 switch (role) {
580 case Qt::DisplayRole:
581 return act->text();
582
583 case Qt::DecorationRole:
584 return act->icon();
585
586 default:
587 break;
588 }
589 return QVariant();
590}
591
593{
595 d->m_tag = tag;
596 update();
597}
598
600{
602 beginResetModel();
603 d->updateRef();
604 endResetModel();
605}
606
616
628
629QAction *RibbonActionsManagerModel::indexToAction(QModelIndex index) const
630{
631 Q_D(const RibbonActionsManagerModel);
632 if (!index.isValid()) {
633 return Q_NULLPTR;
634 }
635 if (index.row() >= d->count()) {
636 return Q_NULLPTR;
637 }
638 return d->at(index.row());
639}
640
646{
648 d->m_seatchText = text;
649 update();
650}
651
653{
655 if (isdelete && (tag == d->m_tag)) {
657 update();
658 } else {
659 if (tag == d->m_tag) {
660 update();
661 }
662 }
663}
664
QAction * indexToAction(QModelIndex index) const
void search(const QString &text)
查找
virtual int rowCount(const QModelIndex &parent) const override
virtual QVariant data(const QModelIndex &index, int role) const override
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
void onActionTagChanged(int tag, bool isdelete)
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
void setupActionsManager(RibbonActionsManager *m)
用于管理 Ribbon 的所有 Action
void setAllActionCanCustomize(bool on=true)
此函数用于设置所有管理的action都可以自定义编辑
QSet< QAction * > autoRegisterWidgetActions(QWidget *w, int tag, bool enableEmit=false)
自动加载action
void unregisterAction(QAction *act, bool enableEmit=true)
取消action的注册
void actionTagChanged(int tag, bool isDeleted)
标签变化触发的信号,变化包括新增和删除
QString tagName(int tag) const
获取tag对应的中文名字
QList< QAction * > search(const QString &text)
根据标题查找action
QList< int > actionTags() const
获取所有的标签
QString key(QAction *act) const
通过action找到key
void onPageTitleChanged(const QString &title)
autoRegisteActions函数会关联此槽,在标签内容改变时改变tag 对应 文本
bool registerAction(QAction *act, int tag, const QString &key=QString(), bool enableEmit=true)
把action注册到管理器中,实现action的管理
QList< QAction * > actions(int tag) const
根据tag得到actions
@ NotInRibbonPageTag
不在功能区的标签autoRegisterActions 函数会遍历所有page的action以及RibbonBar下的action,如果两个
@ AutoPageDistinguishBeginTag
自动按Page划分的标签起始,在 autoRegisterActions 函数会用到
@ CommonlyUsedActionTag
预设tag-常用命令
int count() const
返回所有管理的action数
QAction * action(const QString &key) const
通过key获取action
void onActionDestroyed(QObject *o)
action 被delete时,将触发此槽把管理的action删除
QMap< int, RibbonPage * > autoRegisterActions(RibbonBar *bar)
自动加载RibbonBar的action 此函数会遍历RibbonBar 下的所有子object,找到action注册, 并会遍历所有RibbonPage,把RibbonPage下的action按Rib...
void setTagName(int tag, const QString &name)
设置tag对应的名字,通过这个可以得到tag和文本的映射
QList< QAction * > allActions() const
返回所有管理的actions
RibbonBar 继承 QMenuBar, 在 RibbonWindow 中直接替换了原来的 QMenuBar
Definition ribbonbar.h:99
QList< RibbonPage * > pages(bool getAll=true) const
获取当前显示的所有的RibbonPage,包含未显示的RibbonPageContext的RibbonPage也一并返回
static void setCanCustomize(QObject *obj, bool canbe=true)
group 用于对 ribbon 页窗口中的控件进行分组
Definition ribbongroup.h:29
一项 ribbon tab 页
Definition ribbonpage.h:30
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define Q_NULLPTR
Copyleft (C) 2025 maminjie canpool@163.com SPDX-License-Identifier: MulanPSL-2.0
#define QX_FINI_PRIVATE()
#define QX_RIBBON_END_NAMESPACE
#define QX_RIBBON_BEGIN_NAMESPACE
const char * name
Definition qxtheme.cpp:25
QColor text