Turn SpinBox Delegate example into snippets

The essence of the example was already fully quoted in the
model/view documentation. Move the code into a snippet
source, and update the screenshot.

Fixes: QTBUG-119976
Pick-to: 6.7 6.6
Change-Id: Id2f10bb26a650419969bbfa9b76cb74babd3319e
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Andreas Eliasson <andreas.eliasson@qt.io>
This commit is contained in:
Volker Hilsheimer 2023-12-19 11:16:23 +01:00
parent 7996a3fc7f
commit 99eaae4323
15 changed files with 62 additions and 288 deletions

View File

@ -1,118 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example itemviews/spinboxdelegate
\title Spin Box Delegate Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The Spin Box Delegate example shows how to create an editor for a custom delegate in
the model/view framework by reusing a standard Qt editor widget.
The model/view framework provides a standard delegate that is used by default
with the standard view classes. For most purposes, the selection of editor
widgets available through this delegate is sufficient for editing text, boolean
values, and other simple data types. However, for specific data types, it is
sometimes necessary to use a custom delegate to either display the data in a
specific way, or allow the user to edit it with a custom control.
\image spinboxdelegate-example.png
This concepts behind this example are covered in the
\l{Model/View Programming#Delegate Classes}{Delegate Classes} chapter
of the \l{Model/View Programming} overview.
\section1 SpinBoxDelegate Class Definition
The definition of the delegate is as follows:
\snippet itemviews/spinboxdelegate/delegate.h 0
The delegate class declares only those functions that are needed to
create an editor widget, display it at the correct location in a view,
and communicate with a model. Custom delegates can also provide their
own painting code by reimplementing the \c paintEvent() function.
Furthermore it is also possible to reuse (and avoid deleting) the editor
widget by reimplementing the \a destroyEditor() function. A reused widget
could be a mutable member created in the constructor and deleted in
the destructor.
\section1 SpinBoxDelegate Class Implementation
Delegates are often stateless. The constructor only needs to
call the base class's constructor with the parent QObject as its
argument:
\snippet itemviews/spinboxdelegate/delegate.cpp 0
Since the delegate is a subclass of QStyledItemDelegate, the data it retrieves
from the model is displayed in a default style, and we do not need to
provide a custom \c paintEvent().
The \c createEditor() function returns an editor widget, in this case a
spin box that restricts values from the model to integers from 0 to 100
inclusive.
\snippet itemviews/spinboxdelegate/delegate.cpp 1
We install an event filter on the spin box to ensure that it behaves in
a way that is consistent with other delegates. The implementation for
the event filter is provided by the base class.
The \c setEditorData() function reads data from the model, converts it
to an integer value, and writes it to the editor widget.
\snippet itemviews/spinboxdelegate/delegate.cpp 2
Since the view treats delegates as ordinary QWidget instances, we have
to use a static cast before we can set the value in the spin box.
The \c setModelData() function reads the contents of the spin box, and
writes it to the model.
\snippet itemviews/spinboxdelegate/delegate.cpp 3
We call \l{QSpinBox::interpretText()}{interpretText()} to make sure that
we obtain the most up-to-date value in the spin box.
The \c updateEditorGeometry() function updates the editor widget's
geometry using the information supplied in the style option. This is the
minimum that the delegate must do in this case.
\snippet itemviews/spinboxdelegate/delegate.cpp 4
More complex editor widgets may divide the rectangle available in
\c{option.rect} between different child widgets if required.
\section1 The Main Function
This example is written in a slightly different way to many of the
other examples supplied with Qt. To demonstrate the use of a custom
editor widget in a standard view, it is necessary to set up a model
containing some arbitrary data and a view to display it.
We set up the application in the normal way, construct a standard item
model to hold some data, set up a table view to use the data in the
model, and construct a custom delegate to use for editing:
\snippet itemviews/spinboxdelegate/main.cpp 0
The table view is informed about the delegate, and will use it to
display each of the items. Since the delegate is a subclass of
QStyledItemDelegate, each cell in the table will be rendered using standard
painting operations.
We insert some arbitrary data into the model for demonstration purposes:
\snippet itemviews/spinboxdelegate/main.cpp 1
\snippet itemviews/spinboxdelegate/main.cpp 2
Finally, the table view is displayed with a window title, and we start
the application's event loop:
\snippet itemviews/spinboxdelegate/main.cpp 3
Each of the cells in the table can now be edited in the usual way, but
the spin box ensures that the data returned to the model is always
constrained by the values allowed by the spin box delegate.
*/

View File

@ -9,6 +9,5 @@ qt_internal_add_example(customsortfiltermodel)
qt_internal_add_example(editabletreemodel)
qt_internal_add_example(fetchmore)
qt_internal_add_example(frozencolumn)
qt_internal_add_example(spinboxdelegate)
qt_internal_add_example(spreadsheet)
qt_internal_add_example(stardelegate)

View File

@ -8,6 +8,5 @@ SUBDIRS = addressbook \
fetchmore \
frozencolumn \
simpletreemodel \
spinboxdelegate \
spreadsheet \
stardelegate

View File

@ -1,37 +0,0 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(spinboxdelegate LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/spinboxdelegate")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(spinboxdelegate
delegate.cpp delegate.h
main.cpp
)
set_target_properties(spinboxdelegate PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(spinboxdelegate PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS spinboxdelegate
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,29 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DELEGATE_H
#define DELEGATE_H
#include <QStyledItemDelegate>
//! [0]
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
};
//! [0]
#endif

View File

@ -1,48 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
/*
main.cpp
A simple example that shows how a view can use a custom delegate to edit
data obtained from a model.
*/
#include "delegate.h"
#include <QApplication>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableView>
//! [0]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QStandardItemModel model(4, 2);
QTableView tableView;
tableView.setModel(&model);
SpinBoxDelegate delegate;
tableView.setItemDelegate(&delegate);
//! [0]
tableView.horizontalHeader()->setStretchLastSection(true);
//! [1]
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 2; ++column) {
QModelIndex index = model.index(row, column, QModelIndex());
model.setData(index, QVariant((row + 1) * (column + 1)));
}
//! [1] //! [2]
}
//! [2]
//! [3]
tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));
tableView.show();
return app.exec();
}
//! [3]

View File

@ -1,10 +0,0 @@
QT += widgets
requires(qtConfig(tableview))
HEADERS = delegate.h
SOURCES = delegate.cpp \
main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/spinboxdelegate
INSTALLS += target

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -0,0 +1,12 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
add_library(widgets_qitemdelegate_snippets OBJECT
spinbox-delegate.cpp
)
target_link_libraries(widgets_qitemdelegate_snippets PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets
)

View File

@ -1,25 +1,37 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
/*
delegate.cpp
A delegate that allows the user to change integer values from the model
using a spin box widget.
*/
#include "delegate.h"
#include <QStyledItemDelegate>
#include <QSpinBox>
//! [0]
//! [declaration]
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
};
//! [declaration]
//! [constructor]
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
//! [0]
//! [constructor]
//! [1]
//! [createEditor]
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
@ -31,9 +43,9 @@ QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
return editor;
}
//! [1]
//! [createEditor]
//! [2]
//! [setEditorData]
void SpinBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
@ -42,9 +54,9 @@ void SpinBoxDelegate::setEditorData(QWidget *editor,
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
//! [2]
//! [setEditorData]
//! [3]
//! [setModelData]
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
@ -54,13 +66,14 @@ void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
model->setData(index, value, Qt::EditRole);
}
//! [3]
//! [setModelData]
//! [4]
//! [updateEditorGeometry]
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
//! [4]
//! [updateEditorGeometry]

View File

@ -686,9 +686,8 @@
implementations of these functions.
Editors for delegates can be implemented either by using widgets to manage
the editing process or by handling events directly.
The first approach is covered later in this section, and it is also
shown in the \l{Spin Box Delegate Example}{Spin Box Delegate} example.
the editing process or by handling events directly. The first approach is
covered later in this section.
\section2 Using an existing delegate
@ -718,13 +717,15 @@
data entry. We construct a table view to display the contents of
the model, and this will use the custom delegate for editing.
\image spinboxdelegate-example.png
\image spinboxdelegate-example.webp
We subclass the delegate from \l QStyledItemDelegate because we do not want
to write custom display functions. However, we must still provide
functions to manage the editor widget:
\snippet itemviews/spinboxdelegate/delegate.h 0
\snippet qitemdelegate/spinbox-delegate.cpp declaration
\codeline
\snippet qitemdelegate/spinbox-delegate.cpp constructor
Note that no editor widgets are set up when the delegate is
constructed. We only construct an editor widget when it is needed.
@ -738,7 +739,7 @@
supplied with everything that the delegate needs to be able to set up
a suitable widget:
\snippet itemviews/spinboxdelegate/delegate.cpp 1
\snippet qitemdelegate/spinbox-delegate.cpp createEditor
Note that we do not need to keep a pointer to the editor widget because
the view takes responsibility for destroying it when it is no longer
@ -762,7 +763,7 @@
\l{Qt::ItemDataRole}{display role}, and set the value in the
spin box accordingly.
\snippet itemviews/spinboxdelegate/delegate.cpp 2
\snippet qitemdelegate/spinbox-delegate.cpp setEditorData
In this example, we know that the editor widget is a spin box, but we
could have provided different editors for different types of data in
@ -775,7 +776,7 @@
asks the delegate to store the edited value in the model by calling the
\l{QAbstractItemDelegate::setModelData()}{setModelData()} function.
\snippet itemviews/spinboxdelegate/delegate.cpp 3
\snippet qitemdelegate/spinbox-delegate.cpp setModelData
Since the view manages the editor widgets for the delegate, we only
need to update the model with the contents of the editor supplied.
@ -786,8 +787,8 @@
finished editing by emitting the
\l{QAbstractItemDelegate::closeEditor()}{closeEditor()} signal.
The view ensures that the editor widget is closed and destroyed. In
this example, we only provide simple editing facilities, so we need
never emit this signal.
this example, we only provide simple editing facilities, so we never
need to emit this signal.
All the operations on data are performed through the interface
provided by \l QAbstractItemModel. This makes the delegate mostly
@ -806,7 +807,7 @@
the view provides all the necessary geometry information inside a
\l{QStyleOptionViewItem}{view option} object.
\snippet itemviews/spinboxdelegate/delegate.cpp 4
\snippet qitemdelegate/spinbox-delegate.cpp updateEditorGeometry
In this case, we just use the geometry information provided by the
view option in the item rectangle. A delegate that renders items with
@ -2308,7 +2309,6 @@
\section1 Related Examples
\list
\li \l{itemviews/spinboxdelegate}{Spin Box Delegate}
\li \l{itemviews/simpletreemodel}{Simple Tree Model}
\endlist
*/

View File

@ -534,7 +534,7 @@
Other references to delegates in Qt Documentation:
\list
\li \l{Spin Box Delegate Example}
\li \l{Delegate Classes}
\li \l{QAbstractItemDelegate}{QAbstractItemDelegate Class Reference}
\li \l{QSqlRelationalDelegate}{QSqlRelationalDelegate Class Reference}
\li \l{QStyledItemDelegate}{QStyledItemDelegate Class Reference}
@ -826,11 +826,6 @@
\li QDataWidgetMapper to map QLineEdit, QTextEdit and QSpinBox
\li QStandardItemModel
\li Basic QDataWidgetMapper usage
\row
\li Spin Box Delegate
\li QTableView
\li QStandardItemModel
\li Custom delegate that uses a spin box as a cell editor
\row
\li Spreadsheet
\li {2, 1} QTableView

View File

@ -266,8 +266,8 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
made available to delegates with the default item editor
factory. This way, there is no need to subclass QItemDelegate. An
alternative is to reimplement createEditor(), setEditorData(),
setModelData(), and updateEditorGeometry(). This process is
described in the \l{Spin Box Delegate Example}.
setModelData(), and updateEditorGeometry(). This process is described
in the \l{A simple delegate}{Model/View Programming overview documentation}.
\section1 QStyledItemDelegate vs. QItemDelegate
@ -281,8 +281,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
for either class should be equal unless the custom delegate needs to use
the style for drawing.
\sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate,
{Spin Box Delegate Example}
\sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate
*/
/*!

View File

@ -204,8 +204,7 @@ public:
documentation for details.
\sa {Delegate Classes}, QItemDelegate, QAbstractItemDelegate, QStyle,
{Spin Box Delegate Example}, {Star Delegate Example}, {Color
Editor Factory Example}
{Star Delegate Example}, {Color Editor Factory Example}
*/