Cleanup StarDelegate example

Cleanup the StarDelegate example:
 - use QStyledItemDelegate instead QItemDelegate
 - use nullptr and other useful c++11 constructs
 - include the correct headers

Change-Id: If2f65fe7cbdcdd4571d10ffa98d36eeab7836bbb
Reviewed-by: Sze Howe Koh <szehowe.koh@gmail.com>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Luca Beldi <v.ronin@yahoo.it>
This commit is contained in:
Christian Ehrlicher 2018-11-22 21:21:25 +01:00
parent 51f6d5d8c2
commit 1cfe064632
8 changed files with 40 additions and 50 deletions

View File

@ -42,11 +42,11 @@
editing takes place. editing takes place.
Delegates are subclasses of QAbstractItemDelegate. Qt provides Delegates are subclasses of QAbstractItemDelegate. Qt provides
QItemDelegate, which inherits QAbstractItemDelegate and handles QStyledItemDelegate, which inherits QAbstractItemDelegate and handles
the most common data types (notably \c int and QString). If we the most common data types (notably \c int and QString). If we
need to support custom data types, or want to customize the need to support custom data types, or want to customize the
rendering or the editing for existing data types, we can subclass rendering or the editing for existing data types, we can subclass
QAbstractItemDelegate or QItemDelegate. See \l{Delegate Classes} QAbstractItemDelegate or QStyledItemDelegate. See \l{Delegate Classes}
for more information about delegates, and \l{Model/View for more information about delegates, and \l{Model/View
Programming} if you need a high-level introduction to Qt's Programming} if you need a high-level introduction to Qt's
model/view architecture (including delegates). model/view architecture (including delegates).
@ -62,9 +62,9 @@
expressed as stars, such as "2 out of 5 stars" or "5 out of expressed as stars, such as "2 out of 5 stars" or "5 out of
6 stars". 6 stars".
\li \c StarDelegate inherits QItemDelegate and provides support \li \c StarDelegate inherits QStyledItemDelegate and provides support
for \c StarRating (in addition to the data types already for \c StarRating (in addition to the data types already
handled by QItemDelegate). handled by QStyledItemDelegate).
\li \c StarEditor inherits QWidget and is used by \c StarDelegate \li \c StarEditor inherits QWidget and is used by \c StarDelegate
to let the user edit a star rating using the mouse. to let the user edit a star rating using the mouse.
@ -80,12 +80,12 @@
\snippet itemviews/stardelegate/stardelegate.h 0 \snippet itemviews/stardelegate/stardelegate.h 0
All public functions are reimplemented virtual functions from All public functions are reimplemented virtual functions from
QItemDelegate to provide custom rendering and editing. QStyledItemDelegate to provide custom rendering and editing.
\section1 StarDelegate Class Implementation \section1 StarDelegate Class Implementation
The \l{QAbstractItemDelegate::}{paint()} function is The \l{QAbstractItemDelegate::}{paint()} function is
reimplemented from QItemDelegate and is called whenever the view reimplemented from QStyledItemDelegate and is called whenever the view
needs to repaint an item: needs to repaint an item:
\snippet itemviews/stardelegate/stardelegate.cpp 0 \snippet itemviews/stardelegate/stardelegate.cpp 0
@ -93,7 +93,7 @@
The function is invoked once for each item, represented by a The function is invoked once for each item, represented by a
QModelIndex object from the model. If the data stored in the item QModelIndex object from the model. If the data stored in the item
is a \c StarRating, we paint it ourselves; otherwise, we let is a \c StarRating, we paint it ourselves; otherwise, we let
QItemDelegate paint it for us. This ensures that the \c QStyledItemDelegate paint it for us. This ensures that the \c
StarDelegate can handle the most common data types. StarDelegate can handle the most common data types.
If the item is a \c StarRating, we draw the background if the If the item is a \c StarRating, we draw the background if the

View File

@ -101,10 +101,7 @@ int main(int argc, char *argv[])
tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked
| QAbstractItemView::SelectedClicked); | QAbstractItemView::SelectedClicked);
tableWidget.setSelectionBehavior(QAbstractItemView::SelectRows); tableWidget.setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget.setHorizontalHeaderLabels({"Title", "Genre", "Artist", "Rating"});
QStringList headerLabels;
headerLabels << "Title" << "Genre" << "Artist" << "Rating";
tableWidget.setHorizontalHeaderLabels(headerLabels);
populateTableWidget(&tableWidget); populateTableWidget(&tableWidget);

View File

@ -65,7 +65,7 @@ void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->fillRect(option.rect, option.palette.highlight()); painter->fillRect(option.rect, option.palette.highlight());
starRating.paint(painter, option.rect, option.palette, starRating.paint(painter, option.rect, option.palette,
StarRating::ReadOnly); StarRating::EditMode::ReadOnly);
} else { } else {
QStyledItemDelegate::paint(painter, option, index); QStyledItemDelegate::paint(painter, option, index);
} }
@ -79,9 +79,8 @@ QSize StarDelegate::sizeHint(const QStyleOptionViewItem &option,
if (index.data().canConvert<StarRating>()) { if (index.data().canConvert<StarRating>()) {
StarRating starRating = qvariant_cast<StarRating>(index.data()); StarRating starRating = qvariant_cast<StarRating>(index.data());
return starRating.sizeHint(); return starRating.sizeHint();
} else {
return QStyledItemDelegate::sizeHint(option, index);
} }
return QStyledItemDelegate::sizeHint(option, index);
} }
//! [1] //! [1]
@ -96,9 +95,8 @@ QWidget *StarDelegate::createEditor(QWidget *parent,
connect(editor, &StarEditor::editingFinished, connect(editor, &StarEditor::editingFinished,
this, &StarDelegate::commitAndCloseEditor); this, &StarDelegate::commitAndCloseEditor);
return editor; return editor;
} else {
return QStyledItemDelegate::createEditor(parent, option, index);
} }
return QStyledItemDelegate::createEditor(parent, option, index);
} }
//! [2] //! [2]

View File

@ -57,9 +57,8 @@
class StarDelegate : public QStyledItemDelegate class StarDelegate : public QStyledItemDelegate
{ {
Q_OBJECT Q_OBJECT
public: public:
StarDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {} using QStyledItemDelegate::QStyledItemDelegate;
void paint(QPainter *painter, const QStyleOptionViewItem &option, void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override; const QModelIndex &index) const override;

View File

@ -48,11 +48,11 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include "stareditor.h" #include "stareditor.h"
#include "starrating.h" #include "starrating.h"
#include <QtWidgets>
//! [0] //! [0]
StarEditor::StarEditor(QWidget *parent) StarEditor::StarEditor(QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -71,34 +71,36 @@ QSize StarEditor::sizeHint() const
void StarEditor::paintEvent(QPaintEvent *) void StarEditor::paintEvent(QPaintEvent *)
{ {
QPainter painter(this); QPainter painter(this);
myStarRating.paint(&painter, rect(), this->palette(), myStarRating.paint(&painter, rect(), palette(),
StarRating::Editable); StarRating::EditMode::Editable);
} }
//! [1] //! [1]
//! [2] //! [2]
void StarEditor::mouseMoveEvent(QMouseEvent *event) void StarEditor::mouseMoveEvent(QMouseEvent *event)
{ {
int star = starAtPosition(event->x()); const int star = starAtPosition(event->x());
if (star != myStarRating.starCount() && star != -1) { if (star != myStarRating.starCount() && star != -1) {
myStarRating.setStarCount(star); myStarRating.setStarCount(star);
update(); update();
} }
QWidget::mouseMoveEvent(event);
} }
//! [2] //! [2]
//! [3] //! [3]
void StarEditor::mouseReleaseEvent(QMouseEvent * /* event */) void StarEditor::mouseReleaseEvent(QMouseEvent *event)
{ {
emit editingFinished(); emit editingFinished();
QWidget::mouseReleaseEvent(event);
} }
//! [3] //! [3]
//! [4] //! [4]
int StarEditor::starAtPosition(int x) int StarEditor::starAtPosition(int x) const
{ {
int star = (x / (myStarRating.sizeHint().width() const int star = (x / (myStarRating.sizeHint().width()
/ myStarRating.maxStarCount())) + 1; / myStarRating.maxStarCount())) + 1;
if (star <= 0 || star > myStarRating.maxStarCount()) if (star <= 0 || star > myStarRating.maxStarCount())
return -1; return -1;

View File

@ -59,9 +59,8 @@
class StarEditor : public QWidget class StarEditor : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
StarEditor(QWidget *parent = 0); StarEditor(QWidget *parent = nullptr);
QSize sizeHint() const override; QSize sizeHint() const override;
void setStarRating(const StarRating &starRating) { void setStarRating(const StarRating &starRating) {
@ -78,7 +77,7 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override;
private: private:
int starAtPosition(int x); int starAtPosition(int x) const;
StarRating myStarRating; StarRating myStarRating;
}; };

View File

@ -48,19 +48,18 @@
** **
****************************************************************************/ ****************************************************************************/
#include "starrating.h"
#include <QtWidgets> #include <QtWidgets>
#include <cmath> #include <cmath>
#include "starrating.h" constexpr int PaintingScaleFactor = 20;
const int PaintingScaleFactor = 20;
//! [0] //! [0]
StarRating::StarRating(int starCount, int maxStarCount) StarRating::StarRating(int starCount, int maxStarCount)
: myStarCount(starCount),
myMaxStarCount(maxStarCount)
{ {
myStarCount = starCount;
myMaxStarCount = maxStarCount;
starPolygon << QPointF(1.0, 0.5); starPolygon << QPointF(1.0, 0.5);
for (int i = 1; i < 5; ++i) for (int i = 1; i < 5; ++i)
starPolygon << QPointF(0.5 + 0.5 * std::cos(0.8 * i * 3.14), starPolygon << QPointF(0.5 + 0.5 * std::cos(0.8 * i * 3.14),
@ -87,23 +86,19 @@ void StarRating::paint(QPainter *painter, const QRect &rect,
painter->setRenderHint(QPainter::Antialiasing, true); painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(Qt::NoPen); painter->setPen(Qt::NoPen);
painter->setBrush(mode == EditMode::Editable ?
palette.highlight() :
palette.foreground());
if (mode == Editable) { const int yOffset = (rect.height() - PaintingScaleFactor) / 2;
painter->setBrush(palette.highlight());
} else {
painter->setBrush(palette.foreground());
}
int yOffset = (rect.height() - PaintingScaleFactor) / 2;
painter->translate(rect.x(), rect.y() + yOffset); painter->translate(rect.x(), rect.y() + yOffset);
painter->scale(PaintingScaleFactor, PaintingScaleFactor); painter->scale(PaintingScaleFactor, PaintingScaleFactor);
for (int i = 0; i < myMaxStarCount; ++i) { for (int i = 0; i < myMaxStarCount; ++i) {
if (i < myStarCount) { if (i < myStarCount)
painter->drawPolygon(starPolygon, Qt::WindingFill); painter->drawPolygon(starPolygon, Qt::WindingFill);
} else if (mode == Editable) { else if (mode == EditMode::Editable)
painter->drawPolygon(diamondPolygon, Qt::WindingFill); painter->drawPolygon(diamondPolygon, Qt::WindingFill);
}
painter->translate(1.0, 0.0); painter->translate(1.0, 0.0);
} }

View File

@ -51,15 +51,15 @@
#ifndef STARRATING_H #ifndef STARRATING_H
#define STARRATING_H #define STARRATING_H
#include <QMetaType> #include <QPainter>
#include <QPointF> #include <QPolygonF>
#include <QVector> #include <QSize>
//! [0] //! [0]
class StarRating class StarRating
{ {
public: public:
enum EditMode { Editable, ReadOnly }; enum class EditMode { Editable, ReadOnly };
explicit StarRating(int starCount = 1, int maxStarCount = 5); explicit StarRating(int starCount = 1, int maxStarCount = 5);