instAdmin/Cpp/GisDes/SaRibbon/SARibbonBar/SARibbonGalleryGroup.cpp

493 lines
13 KiB
C++
Raw Normal View History

2024-10-29 22:24:50 +08:00
#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);
}
}
}
}