diff options
author | Christian Ehrlicher <[email protected]> | 2023-12-19 09:41:01 +0100 |
---|---|---|
committer | Christian Ehrlicher <[email protected]> | 2024-11-28 10:43:42 +0200 |
commit | 9ecf47a8a8d11227ecf192246d7df7c2c4dc9105 (patch) | |
tree | ed5a0d454fa9ddedf2beee0dc0bbd4d49ec4970d | |
parent | b2f471e18d818253cd93e9c73fec115fa31e3a80 (diff) |
Add QPainterStateGuard
Add QPainterStateGuard as a small RAII helper class to avoid unbalanced
QPainter::save()/restore() calls.
Change-Id: I618a5d720b7bc9267a0fbac7dcc90e61f5d9cefd
Reviewed-by: Volker Hilsheimer <[email protected]>
Reviewed-by: David Faure <[email protected]>
-rw-r--r-- | src/gui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp | 54 | ||||
-rw-r--r-- | src/gui/painting/qpainterstateguard.cpp | 55 | ||||
-rw-r--r-- | src/gui/painting/qpainterstateguard.h | 57 |
4 files changed, 167 insertions, 0 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5fc2e6eb1dc..ef1e23a3490 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -205,6 +205,7 @@ qt_internal_add_module(Gui painting/qpaintengine_raster.cpp painting/qpaintengine_raster_p.h painting/qpaintengineex.cpp painting/qpaintengineex_p.h painting/qpainter.cpp painting/qpainter.h painting/qpainter_p.h + painting/qpainterstateguard.cpp painting/qpainterstateguard.h painting/qpainterpath.cpp painting/qpainterpath.h painting/qpainterpath_p.h painting/qpathclipper.cpp painting/qpathclipper_p.h painting/qpathsimplifier.cpp painting/qpathsimplifier_p.h diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp new file mode 100644 index 00000000000..adcccd60aa1 --- /dev/null +++ b/src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2024 Christian Ehrlicher <[email protected]> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QPaintEvent> +#include <QPainter> +#include <QPainterStateGuard> +#include <QWidget> + + +namespace src_gui_painting_qpainterstateguard { +struct MyWidget : public QWidget +{ + void paintEvent(QPaintEvent *) override; + bool drawText = true; + QLine line; +}; +struct MyGuardWidget : public QWidget +{ + void paintEvent(QPaintEvent *) override; + bool drawText = true; + QLine line; +}; + +//! [0] +void MyWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setPen(Qt::red); + if (drawText) { + painter.save(); + painter.setPen(Qt::blue); + painter.setFont(QFont("Arial", 30)); + painter.drawText(rect(), Qt::AlignCenter, "Qt"); + painter.restore(); // don't forget to restore previous painter state + } + painter.drawLine(line); +} +//! [0] + +//! [1] +void MyGuardWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setPen(Qt::red); + if (drawText) { + QPainterStateGuard guard(&painter) + painter.setPen(Qt::blue); + painter.setFont(QFont("Arial", 30)); + painter.drawText(rect(), Qt::AlignCenter, "Qt"); + } + painter.drawLine(line); +} +//! [1] + +} // src_gui_painting_qpainterstateguard diff --git a/src/gui/painting/qpainterstateguard.cpp b/src/gui/painting/qpainterstateguard.cpp new file mode 100644 index 00000000000..476b6ad8af9 --- /dev/null +++ b/src/gui/painting/qpainterstateguard.cpp @@ -0,0 +1,55 @@ +// Copyright (C) 2024 Christian Ehrlicher <[email protected]> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qpainterstateguard.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QPainterStateGuard + \brief The QPainterStateGuard is a RAII convenience class for balanced + QPainter::save() and QPainter::restore() calls. + \since 6.9 + + \inmodule QtGui + \ingroup painting + + \reentrant + + \sa QPainter + + QPainterStateGuard should be used everywhere as a replacement for QPainter::save() + to make sure that the corresponding QPainter::restore() is called upon finishing + of the painting routine to avoid unbalanced calls between those two functions. + + Example with QPainter::save()/QPainter::restore(): + \snippet code/src_gui_painting_qpainterstateguard.cpp 0 + + Example with QPainterStateGuard: + \snippet code/src_gui_painting_qpainterstateguard.cpp 1 +*/ + +/*! + \fn QPainterStateGuard::QPainterStateGuard(QPainter *painter, InitialState state = Save) + Constructs a QPainterStateGuard and calls save() on \a painter if \a state + is \c Save (which is the default). When QPainterStateGuard is destroyed, restore() + is called as often as save() was called to restore the QPainter's state. +*/ + +/*! + \fn QPainterStateGuard::~QPainterStateGuard() + Destroys the QPainterStateGuard instance and calls restore() as often as save() + was called to restore the QPainter's state. +*/ + +/*! + \fn void QPainterStateGuard::save() + Calls QPainter::save() and increases the internal save/restore counter by one. +*/ + +/*! + \fn void QPainterStateGuard::restore() + Calls QPainter::restore() if the internal save/restore counter is greater than zero. +*/ + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpainterstateguard.h b/src/gui/painting/qpainterstateguard.h new file mode 100644 index 00000000000..dcb7b48f9b0 --- /dev/null +++ b/src/gui/painting/qpainterstateguard.h @@ -0,0 +1,57 @@ +// Copyright (C) 2024 Christian Ehrlicher <[email protected]> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPAINTERSTATEGUARD_H +#define QPAINTERSTATEGUARD_H + +#include <QtCore/qtclasshelpermacros.h> +#include <QtGui/qpainter.h> + +QT_BEGIN_NAMESPACE + +class QPainterStateGuard +{ + Q_DISABLE_COPY_MOVE(QPainterStateGuard) +public: + enum InitialState + { + Save, + NoSave, + }; + + Q_NODISCARD_CTOR + explicit QPainterStateGuard(QPainter *painter, InitialState state = Save) + : m_painter(painter) + { + Q_ASSERT(painter); + if (state == InitialState::Save) + save(); + } + + ~QPainterStateGuard() + { + while (m_level > 0) + restore(); + } + + void save() + { + m_painter->save(); + ++m_level; + } + + void restore() + { + Q_ASSERT(m_level > 0); + --m_level; + m_painter->restore(); + } + +private: + QPainter *m_painter; + int m_level = 0; +}; + +QT_END_NAMESPACE + +#endif // QPAINTERSTATEGUARD_H |