QtCanpool 3.3.0
载入中...
搜索中...
未找到
ribbongallerygroup.cpp
浏览该文件的文档.
1
7
8#include <QActionGroup>
9#include <QDebug>
10#include <QItemSelectionModel>
11#include <QPainter>
12
14
15/* RibbonGalleryItemPrivate */
16class RibbonGalleryItemPrivate
17{
18public:
19 RibbonGalleryItemPrivate();
20public:
21 QMap<int, QVariant> m_datas;
22 Qt::ItemFlags m_flags;
23 QAction *m_action;
24};
25
26RibbonGalleryItemPrivate::RibbonGalleryItemPrivate()
27 : m_flags(Qt::ItemIsEnabled | Qt::ItemIsSelectable)
28 , m_action(Q_NULLPTR)
29{
30}
31
32/* RibbonGalleryItem */
33RibbonGalleryItem::RibbonGalleryItem()
34 : d(new RibbonGalleryItemPrivate)
35{
36 setTextAlignment(Qt::AlignTop | Qt::AlignHCenter);
37}
38
39RibbonGalleryItem::RibbonGalleryItem(const QString &text, const QIcon &icon)
41{
44}
45
51
56
57void RibbonGalleryItem::setData(int role, const QVariant &data)
58{
59 d->m_datas[role] = data;
60}
61
62QVariant RibbonGalleryItem::data(int role) const
63{
64 if (d->m_action) {
65 switch (role) {
66 case Qt::DisplayRole:
67 return d->m_action->text();
68
69 case Qt::ToolTipRole:
70 return d->m_action->toolTip();
71
72 case Qt::DecorationRole:
73 return d->m_action->icon();
74 default:
75 break;
76 }
77 }
78 return d->m_datas.value(role);
79}
80
81void RibbonGalleryItem::setText(const QString &text)
82{
83 setData(Qt::DisplayRole, text);
84}
85
87{
88 return data(Qt::DisplayRole).toString();
89}
90
92{
93 setData(Qt::ToolTipRole, text);
94}
95
97{
98 return data(Qt::ToolTipRole).toString();
99}
100
101void RibbonGalleryItem::setIcon(const QIcon &ico)
102{
103 setData(Qt::DecorationRole, ico);
104}
105
107{
108 return qvariant_cast<QIcon>(data(Qt::DecorationRole));
109}
110
112{
113 return (d->m_flags & Qt::ItemIsSelectable);
114}
115
116void RibbonGalleryItem::setSelectable(bool isSelectable)
117{
118 if (isSelectable) {
119 d->m_flags |= Qt::ItemIsSelectable;
120 } else {
121 d->m_flags &= ~Qt::ItemIsSelectable;
122 }
123}
124
126{
127 return (d->m_flags & Qt::ItemIsEnabled);
128}
129
131{
132 if (d->m_action) {
133 d->m_action->setEnabled(isEnable);
134 }
135
136 if (isEnable) {
137 d->m_flags |= Qt::ItemIsEnabled;
138 } else {
139 d->m_flags &= ~Qt::ItemIsEnabled;
140 }
141}
142
143void RibbonGalleryItem::setFlags(Qt::ItemFlags flag)
144{
145 d->m_flags = flag;
146 if (d->m_action) {
147 d->m_action->setEnabled(flag & Qt::ItemIsEnabled);
148 }
149}
150
151Qt::ItemFlags RibbonGalleryItem::flags() const
152{
153 return d->m_flags;
154}
155
157{
158 d->m_action = act;
159 if (Q_NULLPTR == act) {
160 return;
161 }
162 if (act->isEnabled()) {
163 d->m_flags |= Qt::ItemIsEnabled;
164 } else {
165 d->m_flags &= ~Qt::ItemIsEnabled;
166 }
167}
168
170{
171 return d->m_action;
172}
173
175{
176 setData(Qt::TextAlignmentRole, (int)a);
177}
178
180{
181 return qvariant_cast<Qt::Alignment>(data(Qt::TextAlignmentRole));
182}
183
184/* RibbonGalleryGroupItemDelegate */
186 : QStyledItemDelegate(parent)
187 , m_group(group)
188{
189}
190
191void RibbonGalleryGroupItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
192 const QModelIndex &index) const
193{
194 if (Q_NULLPTR == m_group) {
195 return;
196 }
197 switch (m_group->galleryGroupStyle()) {
199 paintIconWithText(painter, option, index);
200 break;
202 paintIconWithTextWordWrap(painter, option, index);
203 break;
205 paintIconOnly(painter, option, index);
206 break;
207 default:
208 paintIconWithText(painter, option, index);
209 break;
210 }
211}
212
213void RibbonGalleryGroupItemDelegate::paintIconOnly(QPainter *painter, const QStyleOptionViewItem &option,
214 const QModelIndex &index) const
215{
216 QStyle *style = m_group->style();
217 int sp = m_group->spacing();
218 QRect rect = option.rect;
219 rect.adjust(sp, sp, -sp, -sp);
220 painter->save();
221 painter->setClipRect(rect);
222 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, m_group);
223 // draw the icon
224 QRect iconRect = option.rect;
225 sp += 2;
226 iconRect.adjust(sp, sp, -sp, -sp);
227 QIcon ico = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
228 ico.paint(painter, iconRect, Qt::AlignCenter, QIcon::Normal, QIcon::On);
229 painter->restore();
230}
231
232void RibbonGalleryGroupItemDelegate::paintIconWithText(QPainter *painter, const QStyleOptionViewItem &option,
233 const QModelIndex &index) const
234{
235 QStyledItemDelegate::paint(painter, option, index);
236}
237
238void RibbonGalleryGroupItemDelegate::paintIconWithTextWordWrap(QPainter *painter, const QStyleOptionViewItem &option,
239 const QModelIndex &index) const
240{
241 QStyledItemDelegate::paint(painter, option, index);
242}
243
244QSize RibbonGalleryGroupItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
245{
246 Q_UNUSED(index);
247 Q_UNUSED(option);
248 return m_group->gridSize();
249}
250
251/* RibbonGalleryGroupModel */
253 : QAbstractListModel(parent)
254{
255}
256
261
262int RibbonGalleryGroupModel::rowCount(const QModelIndex &parent) const
263{
264 return (parent.isValid() ? 0 : m_items.count());
265}
266
267Qt::ItemFlags RibbonGalleryGroupModel::flags(const QModelIndex &index) const
268{
269 if (!index.isValid() || (index.row() >= m_items.count())) {
270 return Qt::NoItemFlags;
271 }
272 return m_items.at(index.row())->flags();
273}
274
275QVariant RibbonGalleryGroupModel::data(const QModelIndex &index, int role) const
276{
277 if (!index.isValid() || (index.row() >= m_items.count())) {
278 return QVariant();
279 }
280 return m_items.at(index.row())->data(role);
281}
282
283QModelIndex RibbonGalleryGroupModel::index(int row, int column, const QModelIndex &parent) const
284{
285 if (hasIndex(row, column, parent)) {
286 return createIndex(row, column, m_items.at(row));
287 }
288 return QModelIndex();
289}
290
291bool RibbonGalleryGroupModel::setData(const QModelIndex &index, const QVariant &value, int role)
292{
293 if (!index.isValid() || (index.row() >= m_items.count())) {
294 return false;
295 }
296
297 m_items.at(index.row())->setData(role, value);
298 return true;
299}
300
302{
304 qDeleteAll(m_items);
305 m_items.clear();
307}
308
310{
311 return m_items.value(row);
312}
313
315{
317 m_items.insert(row, item);
319}
320
322{
323 if ((row < 0) || (row >= m_items.count())) {
324 return Q_NULLPTR;
325 }
326
328 RibbonGalleryItem *item = m_items.takeAt(row);
330 return item;
331}
332
334{
335 beginInsertRows(QModelIndex(), m_items.count(), m_items.count() + 1);
336 m_items.append(item);
338}
339
340/* RibbonGalleryGroupPrivate */
341class RibbonGalleryGroupPrivate
342{
344public:
345 RibbonGalleryGroupPrivate();
346 void init();
347 RibbonGalleryGroupModel *groupModel();
348 void itemActivate(const QModelIndex &index, QAction::ActionEvent event);
349 int displayRowCount() const;
350public:
351 QString m_groupTitle;
354 int m_gridMinimumWidth;
355 int m_gridMaximumWidth;
356 QActionGroup *m_actionGroup;
357 bool m_blockRecalc;
358};
359
360RibbonGalleryGroupPrivate::RibbonGalleryGroupPrivate()
361 : m_preStyle(RibbonGalleryGroup::IconWithText)
362 , m_displayRow(RibbonGalleryGroup::DisplayOneRow)
363 , m_gridMinimumWidth(0)
364 , m_gridMaximumWidth(0)
365 , m_blockRecalc(false)
366{
367}
368
369void RibbonGalleryGroupPrivate::init()
370{
371 Q_Q(RibbonGalleryGroup);
372 m_actionGroup = new QActionGroup(q);
373 QObject::connect(m_actionGroup, &QActionGroup::triggered, q, &RibbonGalleryGroup::triggered);
374 QObject::connect(m_actionGroup, &QActionGroup::hovered, q, &RibbonGalleryGroup::hovered);
375}
376
377RibbonGalleryGroupModel *RibbonGalleryGroupPrivate::groupModel()
378{
379 Q_Q(const RibbonGalleryGroup);
380 return qobject_cast<RibbonGalleryGroupModel *>(q->model());
381}
382
383void RibbonGalleryGroupPrivate::itemActivate(const QModelIndex &index, QAction::ActionEvent event)
384{
385 if (index.isValid()) {
386 RibbonGalleryItem *item = static_cast<RibbonGalleryItem *>(index.internalPointer());
387 if (item) {
388 QAction *act = item->action();
389 if (act) {
390 act->activate(event);
391 }
392 }
393 }
394}
395
396int RibbonGalleryGroupPrivate::displayRowCount() const
397{
398 switch (m_displayRow) {
400 return 1;
402 return 2;
404 return 3;
405 }
406 return 1;
407}
408
409/* RibbonGalleryGroup */
411 : QListView(w)
412{
415 d->init();
416 setViewMode(QListView::IconMode);
417 setResizeMode(QListView::Adjust);
418 setSelectionRectVisible(true);
419 setUniformItemSizes(true);
420 setSpacing(1);
421 setItemDelegate(new RibbonGalleryGroupItemDelegate(this, this));
422 connect(this, &QAbstractItemView::clicked, this, &RibbonGalleryGroup::onItemClicked);
423 connect(this, &QAbstractItemView::entered, this, &RibbonGalleryGroup::onItemEntered);
425 setModel(m);
426}
427
432
438{
440 d->m_blockRecalc = on;
441}
442
444{
445 Q_D(const RibbonGalleryGroup);
446 return d->m_blockRecalc;
447}
448
456
458{
459 if (isRecalcGridSizeBlock()) {
460 return;
461 }
462 // 首先通过DisplayRow计算GridSize
464 int dr = d->displayRowCount();
465 int h = galleryHeight / dr;
466 if (h <= 1) {
467 h = galleryHeight;
468 }
469 int w = h;
470 int mw = gridMinimumWidth();
471 if (mw > 0 && w < mw) {
472 w = mw;
473 }
474 mw = gridMaximumWidth();
475 if (mw > 0 && w > mw) {
476 w = mw;
477 }
478 setGridSize(QSize(w, h));
479 // 再通过GalleryGroupStyle确定icon的尺寸
480 // 这个是移动像素,qt在鼠标移动到图标上时会移动一下,给用户明确的动态,导致如果布局很满会超出显示范围,因此要在此基础上缩放一点
481 const int shiftpix = 4;
482 switch (galleryGroupStyle()) {
483 case IconWithText: {
484 int textHeight = fontMetrics().lineSpacing();
485 int iconHeight = h - textHeight - 2 * spacing() - shiftpix;
486 if (iconHeight > 0) {
487 setIconSize(QSize(w - 2 * spacing() - shiftpix, iconHeight));
488 } else {
489 setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
490 }
491 break;
492 }
494 int textHeight = fontMetrics().lineSpacing() * 2;
495 int iconHeight = h - textHeight;
496 if (iconHeight > 0) {
497 setIconSize(QSize(w - 2 * spacing() - shiftpix, iconHeight - 2 * spacing() - shiftpix));
498 } else {
499 setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
500 }
501 break;
502 }
503 case IconOnly: {
504 setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
505 break;
506 }
507 default: {
508 setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
509 break;
510 }
511 }
512#ifdef QX_RIBBON_DEBUG
513 qDebug() << "RibbonGalleryGroup::recalcGridSize(" << galleryHeight << "): gridSize=" << gridSize()
514 << " iconSize=" << iconSize();
515#endif
516}
517
523{
525 d->m_preStyle = style;
526 if (style == IconWithWordWrapText) {
527 setWordWrap(true);
528 } else {
529 setWordWrap(false);
530 }
532}
533
539
540void RibbonGalleryGroup::addItem(const QString &text, const QIcon &icon)
541{
543 RibbonGalleryGroupModel *model = d->groupModel();
544 if (Q_NULLPTR == model) {
545 return;
546 }
547 model->append(new RibbonGalleryItem(text, icon));
548}
549
551{
553 RibbonGalleryGroupModel *model = d->groupModel();
554 if (Q_NULLPTR == model) {
555 return;
556 }
557 d->m_actionGroup->addAction(act);
558 model->append(new RibbonGalleryItem(act));
559}
560
561void RibbonGalleryGroup::addItems(const QList<QAction *> &acts)
562{
564 RibbonGalleryGroupModel *model = d->groupModel();
565 if (Q_NULLPTR == model) {
566 return;
567 }
568 for (QAction *a : acts) {
569 d->m_actionGroup->addAction(a);
570 }
571 for (int i = 0; i < acts.size(); ++i) {
572 model->append(new RibbonGalleryItem(acts[i]));
573 }
574}
575
576void RibbonGalleryGroup::setGroupTitle(const QString &title)
577{
579 d->m_groupTitle = title;
580 Q_EMIT groupTitleChanged(title);
581}
582
584{
585 Q_D(const RibbonGalleryGroup);
586 return d->m_groupTitle;
587}
588
590{
592 RibbonGalleryGroupModel *model = d->groupModel();
593 if (Q_NULLPTR == model) {
594 return;
595 }
596 QModelIndex ind = model->index(i, 0, QModelIndex());
597 QItemSelectionModel *selmodel = selectionModel();
598 if (selmodel) {
599 selmodel->select(ind, QItemSelectionModel::SelectCurrent);
600 }
601}
602
604{
606 d->m_displayRow = r;
608}
609
611{
612 Q_D(const RibbonGalleryGroup);
613 return d->m_displayRow;
614}
615
621{
623 d->m_gridMinimumWidth = w;
624}
625
631{
632 Q_D(const RibbonGalleryGroup);
633 return d->m_gridMinimumWidth;
634}
635
641{
643 d->m_gridMaximumWidth = w;
644}
645
650{
651 Q_D(const RibbonGalleryGroup);
652 return d->m_gridMaximumWidth;
653}
654
656{
657 QSize sz = QListView::sizeHint();
658 Q_D(const RibbonGalleryGroup);
659 int dr = d->displayRowCount();
660 return QSize(sz.width(), sz.height() / dr);
661}
662
668{
669 Q_D(const RibbonGalleryGroup);
670 return d->m_actionGroup;
671}
672
673void RibbonGalleryGroup::onItemClicked(const QModelIndex &index)
674{
676 d->itemActivate(index, QAction::Trigger);
677}
678
679void RibbonGalleryGroup::onItemEntered(const QModelIndex &index)
680{
682 d->itemActivate(index, QAction::Hover);
683}
684
virtual void paintIconWithTextWordWrap(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
RibbonGalleryGroupItemDelegate(RibbonGalleryGroup *group, QObject *parent=Q_NULLPTR)
virtual void paintIconWithText(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
virtual void paintIconOnly(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
virtual int rowCount(const QModelIndex &parent) const override
void append(RibbonGalleryItem *item)
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
RibbonGalleryGroupModel(QObject *parent=Q_NULLPTR)
RibbonGalleryItem * at(int row) const
virtual QVariant data(const QModelIndex &index, int role) const override
void insert(int row, RibbonGalleryItem *item)
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const override
RibbonGalleryItem * take(int row)
GalleryGroupStyle galleryGroupStyle() const
DisplayRow
定义Gallery在一个group下面显示的图标行数
@ DisplayOneRow
显示1行,默认
void triggered(QAction *action)
等同QActionGroup的triggered 所有加入RibbonGalleryGroup的action都会被一个QActionGroup管理,可以通过
void onItemClicked(const QModelIndex &index)
void setGroupTitle(const QString &title)
void onItemEntered(const QModelIndex &index)
void hovered(QAction *action)
等同QActionGroup的hovered 所有加入RibbonGalleryGroup的action都会被一个QActionGroup管理,可以通过
void recalcGridSize()
重新计算grid和icon的尺寸
void setGridMinimumWidth(int w)
设置grid最小的宽度,默认为0(不限制)
void setGridMaximumWidth(int w)
设置grid最大的宽度,默认为0(不限制)
void addItems(const QList< QAction * > &acts)
RibbonGalleryGroup(QWidget *w=Q_NULLPTR)
void setGalleryGroupStyle(GalleryGroupStyle style)
设置默认的预设样式
GalleryGroupStyle
GalleryGroup显示的样式
@ IconWithWordWrapText
图标带文字,文字会换行显示,此模式只会对DisplayOneRow生效,如果不是DisplayOneRow,等同IconWithText
QActionGroup * actionGroup() const
获取RibbonGalleryGroup管理的actiongroup
void setRecalcGridSizeBlock(bool on=true)
是否禁止计算
void addItem(const QString &text, const QIcon &icon)
void groupTitleChanged(const QString &title)
int gridMaximumWidth() const
grid最大的的宽度,默认为0(不限制)
int gridMinimumWidth() const
grid最小的宽度,默认为0(不限制)
virtual Qt::ItemFlags flags() const
Qt::Alignment textAlignment() const
void setToolTip(const QString &text)
void setFlags(Qt::ItemFlags flag)
void setText(const QString &text)
void setSelectable(bool isSelectable)
void setData(int role, const QVariant &data)
void setTextAlignment(Qt::Alignment a)
virtual QVariant data(int role) const
#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
QColor text