summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <[email protected]>2023-12-19 09:41:01 +0100
committerChristian Ehrlicher <[email protected]>2024-11-28 10:43:42 +0200
commit9ecf47a8a8d11227ecf192246d7df7c2c4dc9105 (patch)
treeed5a0d454fa9ddedf2beee0dc0bbd4d49ec4970d
parentb2f471e18d818253cd93e9c73fec115fa31e3a80 (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.txt1
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp54
-rw-r--r--src/gui/painting/qpainterstateguard.cpp55
-rw-r--r--src/gui/painting/qpainterstateguard.h57
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