[kdevelop/kdevelop] plugins: Add gdb pretty-printers for QPoint, QSize and QRect

David Faure <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit b3759e542cd7b53ac5d30d1b314231c06ee2a06a by David Faure.
Committed on 10/08/2026 at 08:55.
Pushed by dfaure into branch 'master'.

Add gdb pretty-printers for QPoint, QSize and QRect

Since Qt 6.10 the coordinates are QCheckedInt<int>, so the raw output
was drowning in QtPrivate::QCheckedIntegers internals. The printers
produce the same text as the QDebug operators, and still work with
older Qt where the members are plain ints.

M  +3    -0    plugins/debuggercommon/tests/debuggees/CMakeLists.txt
A  +30   -0    plugins/debuggercommon/tests/debuggees/qgeometry.cpp  *
M  +44   -0    plugins/gdb/printers/qt.py
M  +19   -0    plugins/gdb/unittests/test_gdbprinters.cpp
M  +1    -0    plugins/gdb/unittests/test_gdbprinters.h

The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


https://invent.kde.org/kdevelop/kdevelop/-/commit/b3759e542cd7b53ac5d30d1b314231c06ee2a06a

diff --git a/plugins/debuggercommon/tests/debuggees/CMakeLists.txt b/plugins/debuggercommon/tests/debuggees/CMakeLists.txt
index 9adb96bc41..1dd31b563d 100644
--- a/plugins/debuggercommon/tests/debuggees/CMakeLists.txt
+++ b/plugins/debuggercommon/tests/debuggees/CMakeLists.txt
@@ -108,6 +108,9 @@ target_link_libraries(debuggee_qsetstring Qt::Core)
 add_debuggable_executable(debuggee_qchar SRCS qchar.cpp)
 target_link_libraries(debuggee_qchar Qt::Core)
 
+add_debuggable_executable(debuggee_qgeometry SRCS qgeometry.cpp)
+target_link_libraries(debuggee_qgeometry Qt::Core)
+
 add_debuggable_executable(debuggee_qpersistentmodelindex SRCS qpersistentmodelindex.cpp)
 target_link_libraries(debuggee_qpersistentmodelindex Qt::Core Qt::Gui)
 
diff --git a/plugins/debuggercommon/tests/debuggees/qgeometry.cpp b/plugins/debuggercommon/tests/debuggees/qgeometry.cpp
new file mode 100644
index 0000000000..ee36b71c12
--- /dev/null
+++ b/plugins/debuggercommon/tests/debuggees/qgeometry.cpp
@@ -0,0 +1,30 @@
+#include <QPoint>
+#include <QRect>
+#include <QSize>
+
+int main()
+{
+    QPoint defaultPoint;
+    QPoint point(1, 2);
+    QPoint negativePoint(-3, -4);
+
+    QSize defaultSize;
+    QSize size(10, 20);
+
+    QRect defaultRect;
+    QRect rect(1, 2, 30, 40);
+    QRect negativeRect(-5, -6, 7, 8);
+    QRect emptyRect(1, 2, 0, 0);
+
+    Q_UNUSED(defaultPoint);
+    Q_UNUSED(point);
+    Q_UNUSED(negativePoint);
+    Q_UNUSED(defaultSize);
+    Q_UNUSED(size);
+    Q_UNUSED(defaultRect);
+    Q_UNUSED(rect);
+    Q_UNUSED(negativeRect);
+    Q_UNUSED(emptyRect);
+
+    return 0; // line 29
+}
diff --git a/plugins/gdb/printers/qt.py b/plugins/gdb/printers/qt.py
index a15162233a..f270df0928 100644
--- a/plugins/gdb/printers/qt.py
+++ b/plugins/gdb/printers/qt.py
@@ -1128,6 +1128,47 @@ class QUuidPrinter:
                                             int(self.val['data4'][4]), int(self.val['data4'][5]),
                                             int(self.val['data4'][6]), int(self.val['data4'][7]))
 
+def checkedIntValue(val):
+    # Since Qt 6.10 the coordinates are QtPrivate::QCheckedIntegers::QCheckedInt<int>, before that plain int
+    try:
+        return int(val['m_i'])
+    except gdb.error:
+        return int(val)
+
+# The geometry printers below deliberately reproduce the QDebug operators, spacing
+# included, so that the debugger shows exactly what a qDebug() of the same value prints.
+
+class QPointPrinter:
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        # same output as QDebug operator<<(QPoint)
+        return "QPoint(%d,%d)" % (checkedIntValue(self.val['xp']), checkedIntValue(self.val['yp']))
+
+class QSizePrinter:
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        # same output as QDebug operator<<(QSize)
+        return "QSize(%d, %d)" % (checkedIntValue(self.val['wd']), checkedIntValue(self.val['ht']))
+
+class QRectPrinter:
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        x1 = checkedIntValue(self.val['x1'])
+        y1 = checkedIntValue(self.val['y1'])
+        x2 = checkedIntValue(self.val['x2'])
+        y2 = checkedIntValue(self.val['y2'])
+        # same output as QDebug operator<<(QRect)
+        return "QRect(%d,%d %dx%d)" % (x1, y1, x2 - x1 + 1, y2 - y1 + 1)
+
 class CborValueType(Enum):
     # converted from qcborvalue.h
     Integer         = 0x00
@@ -1730,6 +1771,9 @@ def build_dictionary ():
     pretty_printers_dict[re.compile('^QSet<.*>$')] = lambda val: QSetPrinter(val)
     pretty_printers_dict[re.compile('^QChar$')] = lambda val: QCharPrinter(val)
     pretty_printers_dict[re.compile('^QUuid$')] = lambda val: QUuidPrinter(val)
+    pretty_printers_dict[re.compile('^QPoint$')] = lambda val: QPointPrinter(val)
+    pretty_printers_dict[re.compile('^QSize$')] = lambda val: QSizePrinter(val)
+    pretty_printers_dict[re.compile('^QRect$')] = lambda val: QRectPrinter(val)
     pretty_printers_dict[re.compile('^QVariant$')] = lambda val: QVariantPrinter(val)
     pretty_printers_dict[re.compile('^QPersistentModelIndex$')] = lambda val: QPersistentModelIndexPrinter(val)
     pretty_printers_dict[re.compile('^QCborArray$')] = lambda val: QCborArrayPrinter(val)
diff --git a/plugins/gdb/unittests/test_gdbprinters.cpp b/plugins/gdb/unittests/test_gdbprinters.cpp
index efac1899b8..8cb7a3e312 100644
--- a/plugins/gdb/unittests/test_gdbprinters.cpp
+++ b/plugins/gdb/unittests/test_gdbprinters.cpp
@@ -835,6 +835,25 @@ void QtPrintersTest::testQChar()
     QVERIFY(gdb.execute("print c").contains("\"k\""));
 }
 
+void QtPrintersTest::testQGeometry()
+{
+    GdbProcess gdb(QStringLiteral("debuggee_qgeometry"));
+    gdb.execute("break qgeometry.cpp:29");
+    gdb.execute("run");
+
+    QCOMPARE(printedValue(gdb, "defaultPoint"), "QPoint(0,0)");
+    QCOMPARE(printedValue(gdb, "point"), "QPoint(1,2)");
+    QCOMPARE(printedValue(gdb, "negativePoint"), "QPoint(-3,-4)");
+
+    QCOMPARE(printedValue(gdb, "defaultSize"), "QSize(-1, -1)");
+    QCOMPARE(printedValue(gdb, "size"), "QSize(10, 20)");
+
+    QCOMPARE(printedValue(gdb, "defaultRect"), "QRect(0,0 0x0)");
+    QCOMPARE(printedValue(gdb, "rect"), "QRect(1,2 30x40)");
+    QCOMPARE(printedValue(gdb, "negativeRect"), "QRect(-5,-6 7x8)");
+    QCOMPARE(printedValue(gdb, "emptyRect"), "QRect(1,2 0x0)");
+}
+
 void QtPrintersTest::testQListPOD()
 {
     GdbProcess gdb(QStringLiteral("debuggee_qlistpod"));
diff --git a/plugins/gdb/unittests/test_gdbprinters.h b/plugins/gdb/unittests/test_gdbprinters.h
index 9837a03d90..0a1e0494e3 100644
--- a/plugins/gdb/unittests/test_gdbprinters.h
+++ b/plugins/gdb/unittests/test_gdbprinters.h
@@ -36,6 +36,7 @@ private Q_SLOTS:
     void testQSetInt();
     void testQSetString();
     void testQChar();
+    void testQGeometry();
     void testQListPOD();
     void testQPersistentModelIndex();
     void testQUuid();
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.