Add checkboxes to resource downloader (#3516)

This commit is contained in:
Alexandru Ionut Tripon
2025-04-29 08:32:30 +03:00
committed by GitHub
32 changed files with 241 additions and 121 deletions

View File

@ -1,9 +1,11 @@
#include "ProjectItem.h"
#include "Common.h"
#include <QApplication>
#include <QDebug>
#include <QIcon>
#include <QPainter>
#include "Common.h"
ProjectItemDelegate::ProjectItemDelegate(QWidget* parent) : QStyledItemDelegate(parent) {}
@ -14,13 +16,20 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
QStyleOptionViewItem opt(option);
initStyleOption(&opt, index);
const QStyle* style = opt.widget == nullptr ? QApplication::style() : opt.widget->style();
auto rect = opt.rect;
if (opt.state & QStyle::State_Selected) {
painter->fillRect(rect, opt.palette.highlight());
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
if (option.state & QStyle::State_Selected && style->objectName() != "windowsvista")
painter->setPen(opt.palette.highlightedText().color());
} else if (opt.state & QStyle::State_MouseOver) {
painter->fillRect(rect, opt.palette.window());
if (opt.features & QStyleOptionViewItem::HasCheckIndicator) {
QStyleOptionViewItem checkboxOpt = makeCheckboxStyleOption(opt, style);
style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &checkboxOpt, painter, opt.widget);
rect.setX(checkboxOpt.rect.right());
}
// The default icon size will be a square (and height is usually the lower value).
@ -42,6 +51,9 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
int x = rect.x() + icon_x_margin;
int y = rect.y() + icon_y_margin;
if (opt.features & QStyleOptionViewItem::HasCheckIndicator)
rect.translate(icon_x_margin / 2, 0);
// Prevent 'scaling null pixmap' warnings
if (icon_width > 0 && icon_height > 0)
opt.icon.paint(painter, x, y, icon_width, icon_height);
@ -56,26 +68,12 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
{ // Title painting
auto title = index.data(UserDataTypes::TITLE).toString();
if (index.data(UserDataTypes::INSTALLED).toBool())
title = tr("%1 [installed]").arg(title);
painter->save();
auto font = opt.font;
if (index.data(UserDataTypes::SELECTED).toBool()) {
// Set nice font
font.setBold(true);
font.setUnderline(true);
}
if (index.data(UserDataTypes::INSTALLED).toBool()) {
auto hRect = opt.rect;
hRect.setX(hRect.x() + 1);
hRect.setY(hRect.y() + 1);
hRect.setHeight(hRect.height() - 2);
hRect.setWidth(hRect.width() - 2);
// Set nice font
font.setItalic(true);
font.setOverline(true);
painter->drawRect(hRect);
}
font.setPointSize(font.pointSize() + 2);
painter->setFont(font);
@ -132,3 +130,56 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
painter->restore();
}
bool ProjectItemDelegate::editorEvent(QEvent* event,
QAbstractItemModel* model,
const QStyleOptionViewItem& option,
const QModelIndex& index)
{
if (!(event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonDblClick))
return false;
auto mouseEvent = (QMouseEvent*)event;
if (mouseEvent->button() != Qt::LeftButton)
return false;
QStyleOptionViewItem opt(option);
initStyleOption(&opt, index);
const QStyle* style = opt.widget == nullptr ? QApplication::style() : opt.widget->style();
const QStyleOptionViewItem checkboxOpt = makeCheckboxStyleOption(opt, style);
if (!checkboxOpt.rect.contains(mouseEvent->x(), mouseEvent->y()))
return false;
// swallow other events
// (prevents item being selected or double click action triggering)
if (event->type() != QEvent::MouseButtonRelease)
return true;
emit checkboxClicked(index);
return true;
}
QStyleOptionViewItem ProjectItemDelegate::makeCheckboxStyleOption(const QStyleOptionViewItem& opt, const QStyle* style) const
{
QStyleOptionViewItem checkboxOpt = opt;
checkboxOpt.state &= ~QStyle::State_HasFocus;
if (checkboxOpt.checkState == Qt::Checked)
checkboxOpt.state |= QStyle::State_On;
else
checkboxOpt.state |= QStyle::State_Off;
QRect checkboxRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &checkboxOpt, opt.widget);
// 5px is the typical top margin for image
// we don't want the checkboxes to be all over the place :)
checkboxOpt.rect = QRect(opt.rect.x() + 5, opt.rect.y() + (opt.rect.height() / 2 - checkboxRect.height() / 2), checkboxRect.width(),
checkboxRect.height());
return checkboxOpt;
}

View File

@ -6,8 +6,7 @@
enum UserDataTypes {
TITLE = 257, // QString
DESCRIPTION = 258, // QString
SELECTED = 259, // bool
INSTALLED = 260 // bool
INSTALLED = 259 // bool
};
/** This is an item delegate composed of:
@ -22,4 +21,12 @@ class ProjectItemDelegate final : public QStyledItemDelegate {
ProjectItemDelegate(QWidget* parent);
void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) override;
signals:
void checkboxClicked(const QModelIndex& index);
private:
QStyleOptionViewItem makeCheckboxStyleOption(const QStyleOptionViewItem& opt, const QStyle* style) const;
};