instAdmin/Cpp/GisDes/SaRibbon/SARibbonBar/SARibbonGalleryGroup.cpp
2024-10-29 22:24:50 +08:00

493 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SARibbonGalleryGroup.h"
#include <QPainter>
#include <QDebug>
#include <QActionGroup>
#include <QItemSelectionModel>
#include "SARibbonElementManager.h"
/**
* @brief The SARibbonGalleryGroupPrivate class
*/
class SARibbonGalleryGroup::PrivateData
{
public:
SARibbonGalleryGroup* q_ptr;
QString mGroupTitle;
SARibbonGalleryGroup::GalleryGroupStyle mPreStyle { SARibbonGalleryGroup::IconWithText };
SARibbonGalleryGroup::DisplayRow mDisplayRow { SARibbonGalleryGroup::DisplayOneRow };
bool mBlockRecalc { false };
int mGridMinimumWidth { 0 }; ///< grid最小宽度
int mGridMaximumWidth { 0 }; ///< grid最大宽度
QActionGroup* mActionGroup { nullptr }; ///< 所有GalleryGroup管理的actions都由这个actiongroup管理
public:
PrivateData(SARibbonGalleryGroup* p) : q_ptr(p)
{
mActionGroup = new QActionGroup(p);
p->connect(mActionGroup, &QActionGroup::triggered, p, &SARibbonGalleryGroup::triggered);
p->connect(mActionGroup, &QActionGroup::hovered, p, &SARibbonGalleryGroup::hovered);
}
};
//===================================================
// SARibbonGalleryGroupItemDelegate
//===================================================
SARibbonGalleryGroupItemDelegate::SARibbonGalleryGroupItemDelegate(SARibbonGalleryGroup* group, QObject* parent)
: QStyledItemDelegate(parent), mGroup(group)
{
}
void SARibbonGalleryGroupItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if (nullptr == mGroup) {
return;
}
switch (mGroup->galleryGroupStyle()) {
case SARibbonGalleryGroup::IconWithText:
paintIconWithText(painter, option, index);
break;
case SARibbonGalleryGroup::IconWithWordWrapText:
paintIconWithTextWordWrap(painter, option, index);
break;
case SARibbonGalleryGroup::IconOnly:
paintIconOnly(painter, option, index);
break;
default:
paintIconWithText(painter, option, index);
break;
}
}
void SARibbonGalleryGroupItemDelegate::paintIconOnly(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyle* style = mGroup->style();
int sp = mGroup->spacing();
sp += 3;
painter->save();
painter->setClipRect(option.rect);
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, mGroup);
// draw the icon
QRect iconRect = option.rect;
iconRect.adjust(sp, sp, -sp, -sp);
QIcon ico = qvariant_cast< QIcon >(index.data(Qt::DecorationRole));
ico.paint(painter, iconRect, Qt::AlignCenter, QIcon::Normal, QIcon::On);
painter->restore();
}
void SARibbonGalleryGroupItemDelegate::paintIconWithText(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyledItemDelegate::paint(painter, option, index);
}
void SARibbonGalleryGroupItemDelegate::paintIconWithTextWordWrap(QPainter* painter,
const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QStyledItemDelegate::paint(painter, option, index);
}
QSize SARibbonGalleryGroupItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
Q_UNUSED(index);
Q_UNUSED(option);
return mGroup->gridSize();
}
//===================================================
// SARibbonGalleryGroupModel
//===================================================
SARibbonGalleryGroupModel::SARibbonGalleryGroupModel(QObject* parent) : QAbstractListModel(parent)
{
}
SARibbonGalleryGroupModel::~SARibbonGalleryGroupModel()
{
clear();
}
int SARibbonGalleryGroupModel::rowCount(const QModelIndex& parent) const
{
return (parent.isValid() ? 0 : mItems.size());
}
Qt::ItemFlags SARibbonGalleryGroupModel::flags(const QModelIndex& index) const
{
if (!index.isValid() || (index.row() >= mItems.size())) {
return (Qt::NoItemFlags);
}
return (mItems.at(index.row())->flags());
}
QVariant SARibbonGalleryGroupModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid() || (index.row() >= mItems.count())) {
return (QVariant());
}
return (mItems.at(index.row())->data(role));
}
QModelIndex SARibbonGalleryGroupModel::index(int row, int column, const QModelIndex& parent) const
{
if (hasIndex(row, column, parent)) {
return (createIndex(row, column, mItems.at(row)));
}
return (QModelIndex());
}
bool SARibbonGalleryGroupModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid() || (index.row() >= mItems.count())) {
return (false);
}
mItems.at(index.row())->setData(role, value);
return (true);
}
void SARibbonGalleryGroupModel::clear()
{
beginResetModel();
for (int i = 0; i < mItems.count(); ++i) {
if (mItems.at(i)) {
delete mItems.at(i);
}
}
mItems.clear();
endResetModel();
}
SARibbonGalleryItem* SARibbonGalleryGroupModel::at(int row) const
{
return (mItems.value(row));
}
void SARibbonGalleryGroupModel::insert(int row, SARibbonGalleryItem* item)
{
beginInsertRows(QModelIndex(), row, row);
mItems.insert(row, item);
endInsertRows();
}
SARibbonGalleryItem* SARibbonGalleryGroupModel::take(int row)
{
if ((row < 0) || (row >= mItems.count())) {
return (0);
}
beginRemoveRows(QModelIndex(), row, row);
SARibbonGalleryItem* item = mItems.takeAt(row);
endRemoveRows();
return (item);
}
void SARibbonGalleryGroupModel::append(SARibbonGalleryItem* item)
{
beginInsertRows(QModelIndex(), mItems.count(), mItems.count() + 1);
mItems.append(item);
endInsertRows();
}
//===================================================
// SARibbonGalleryGroup
//===================================================
SARibbonGalleryGroup::SARibbonGalleryGroup(QWidget* w)
: QListView(w), d_ptr(new SARibbonGalleryGroup::PrivateData(this))
{
setViewMode(QListView::IconMode);
setResizeMode(QListView::Adjust);
setSelectionRectVisible(true);
setUniformItemSizes(true);
setSpacing(1);
setItemDelegate(new SARibbonGalleryGroupItemDelegate(this, this));
connect(this, &QAbstractItemView::clicked, this, &SARibbonGalleryGroup::onItemClicked);
SARibbonGalleryGroupModel* m = new SARibbonGalleryGroupModel(this);
setModel(m);
}
SARibbonGalleryGroup::~SARibbonGalleryGroup()
{
}
/**
* @brief 是否禁止计算
* @param on
*/
void SARibbonGalleryGroup::setRecalcGridSizeBlock(bool on)
{
d_ptr->mBlockRecalc = on;
}
bool SARibbonGalleryGroup::isRecalcGridSizeBlock() const
{
return d_ptr->mBlockRecalc;
}
/**
* @brief 重新计算grid和icon的尺寸
*/
void SARibbonGalleryGroup::recalcGridSize()
{
recalcGridSize(height());
}
void SARibbonGalleryGroup::recalcGridSize(int galleryHeight)
{
if (isRecalcGridSizeBlock()) {
return;
}
// 首先通过DisplayRow计算GridSize
int dr = static_cast< int >(displayRow());
if (dr < 1) {
dr = 1;
} else if (dr > 3) {
dr = 3;
}
int h = galleryHeight / dr;
if (h <= 1) {
h = galleryHeight;
}
int w = h;
if (gridMinimumWidth() > 0) {
if (w < gridMinimumWidth()) {
w = gridMinimumWidth();
}
}
if (gridMaximumWidth() > 0) {
if (w > gridMaximumWidth()) {
w = gridMaximumWidth();
}
}
setGridSize(QSize(w, h));
// 在通过GalleryGroupStyle确定icon的尺寸
const int shiftpix = 4; // 这个是移动像素qt在鼠标移动到图标上时会移动一下给用户明确的动态导致如果布局很满会超出显示范围因此要在此基础上缩放一点
switch (galleryGroupStyle()) {
case IconWithText: {
int textHeight = fontMetrics().lineSpacing();
int iconHeight = h - textHeight - 2 * spacing() - shiftpix;
if (iconHeight > 0) {
setIconSize(QSize(w - 2 * spacing() - shiftpix, iconHeight));
} else {
setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
}
break;
}
case IconWithWordWrapText: {
int textHeight = fontMetrics().lineSpacing() * 2;
int iconHeight = h - textHeight;
if (iconHeight > 0) {
setIconSize(QSize(w - 2 * spacing() - shiftpix, iconHeight - 2 * spacing() - shiftpix));
} else {
setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
}
break;
}
case IconOnly: {
setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
break;
}
default: {
setIconSize(QSize(w - 2 * spacing() - shiftpix, h - 2 * spacing() - shiftpix));
break;
}
}
#if 0
qDebug() << "SARibbonGalleryGroup::recalcGridSize(" << galleryHeight << "): gridSize=" << gridSize()
<< " iconSize=" << iconSize();
#endif
}
///
/// \brief 设置默认的预设样式
/// \param style
///
void SARibbonGalleryGroup::setGalleryGroupStyle(SARibbonGalleryGroup::GalleryGroupStyle style)
{
d_ptr->mPreStyle = style;
if (style == IconWithWordWrapText) {
setWordWrap(true);
}
recalcGridSize();
}
SARibbonGalleryGroup::GalleryGroupStyle SARibbonGalleryGroup::galleryGroupStyle() const
{
return d_ptr->mPreStyle;
}
void SARibbonGalleryGroup::addItem(const QString& text, const QIcon& icon)
{
if (nullptr == groupModel()) {
return;
}
addItem(new SARibbonGalleryItem(text, icon));
}
/**
* @brief 添加一个条目
*
* @param item 条目的内存所有权归属SARibbonGalleryGroup管理
*/
void SARibbonGalleryGroup::addItem(SARibbonGalleryItem* item)
{
if (nullptr == groupModel()) {
return;
}
groupModel()->append(item);
}
void SARibbonGalleryGroup::addActionItem(QAction* act)
{
if (nullptr == groupModel()) {
return;
}
d_ptr->mActionGroup->addAction(act);
groupModel()->append(new SARibbonGalleryItem(act));
}
void SARibbonGalleryGroup::addActionItemList(const QList< QAction* >& acts)
{
SARibbonGalleryGroupModel* model = groupModel();
if (nullptr == model) {
return;
}
for (QAction* a : acts) {
d_ptr->mActionGroup->addAction(a);
}
for (int i = 0; i < acts.size(); ++i) {
model->append(new SARibbonGalleryItem(acts[ i ]));
}
}
///
/// \brief 构建一个model这个model的父类是SARibbonGalleryGroup如果要共享model需要手动处理model的父类
///
void SARibbonGalleryGroup::setupGroupModel()
{
setModel(new SARibbonGalleryGroupModel(this));
}
SARibbonGalleryGroupModel* SARibbonGalleryGroup::groupModel()
{
return (qobject_cast< SARibbonGalleryGroupModel* >(model()));
}
void SARibbonGalleryGroup::setGroupTitle(const QString& title)
{
d_ptr->mGroupTitle = title;
Q_EMIT groupTitleChanged(d_ptr->mGroupTitle);
}
QString SARibbonGalleryGroup::groupTitle() const
{
return (d_ptr->mGroupTitle);
}
void SARibbonGalleryGroup::selectByIndex(int i)
{
SARibbonGalleryGroupModel* model = groupModel();
if (nullptr == model) {
return;
}
QModelIndex ind = model->index(i, 0, QModelIndex());
QItemSelectionModel* selmodel = selectionModel();
if (selmodel) {
selmodel->select(ind, QItemSelectionModel::SelectCurrent);
}
}
/**
* @brief 设置显示的行数
* @param r
*/
void SARibbonGalleryGroup::setDisplayRow(DisplayRow r)
{
d_ptr->mDisplayRow = r;
recalcGridSize();
}
/**
* @brief Gallery显示的行数
* @return
*/
SARibbonGalleryGroup::DisplayRow SARibbonGalleryGroup::displayRow() const
{
return d_ptr->mDisplayRow;
}
/**
* @brief 设置grid最小的宽度默认为0不限制
* @param w
*/
void SARibbonGalleryGroup::setGridMinimumWidth(int w)
{
d_ptr->mGridMinimumWidth = w;
}
/**
* @brief grid最小的宽度默认为0不限制
* @return
*/
int SARibbonGalleryGroup::gridMinimumWidth() const
{
return d_ptr->mGridMinimumWidth;
}
/**
* @brief 设置grid最大的宽度默认为0不限制
* @param w
*/
void SARibbonGalleryGroup::setGridMaximumWidth(int w)
{
d_ptr->mGridMaximumWidth = w;
}
/**
* @brief grid最大的的宽度默认为0不限制
* @param w
*/
int SARibbonGalleryGroup::gridMaximumWidth() const
{
return d_ptr->mGridMaximumWidth;
}
/**
* @brief 获取SARibbonGalleryGroup管理的actiongroup
* @return
*/
QActionGroup* SARibbonGalleryGroup::actionGroup() const
{
return d_ptr->mActionGroup;
}
void SARibbonGalleryGroup::onItemClicked(const QModelIndex& index)
{
if (index.isValid()) {
SARibbonGalleryItem* item = (SARibbonGalleryItem*)index.internalPointer();
if (item) {
QAction* act = item->action();
if (act) {
act->activate(QAction::Trigger);
}
}
}
}
void SARibbonGalleryGroup::onItemEntered(const QModelIndex& index)
{
if (index.isValid()) {
SARibbonGalleryItem* item = (SARibbonGalleryItem*)index.internalPointer();
if (item) {
QAction* act = item->action();
if (act) {
act->activate(QAction::Hover);
}
}
}
}