KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
DebugWindow.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
19#include "DebugWindow_p.h"
20#include "DockRegistry_p.h"
21#include "FloatingWindow_p.h"
22#include "LayoutSaver.h"
23#include "LayoutWidget_p.h"
24#include "MainWindow.h"
25#include "ObjectViewer_p.h"
26#include "Qt5Qt6Compat_p.h"
27
28#include <QVBoxLayout>
29#include <QHBoxLayout>
30#include <QPushButton>
31#include <QLineEdit>
32#include <QSpinBox>
33#include <QMessageBox>
34#include <QApplication>
35#include <QMouseEvent>
36#include <QWindow>
37#include <QFileDialog>
38#include <QAbstractNativeEventFilter>
39#include <QTimer>
40
41#ifdef Q_OS_WIN
42#include <windows.h>
43#include <winuser.h>
44#endif
45
46// clazy:excludeall=range-loop
47
48using namespace KDDockWidgets;
49using namespace KDDockWidgets::Debug;
50
51class DebugAppEventFilter : public QAbstractNativeEventFilter
52{
53public:
54 DebugAppEventFilter()
55 {
56 }
57 ~DebugAppEventFilter();
58#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
59 bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
60#else
61 bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
62#endif
63 {
64#ifdef Q_OS_WIN
65 if (eventType != "windows_generic_MSG")
66 return false;
67 auto msg = static_cast<MSG *>(message);
68
69 if (msg->message == WM_NCCALCSIZE)
70 qDebug() << "Got WM_NCCALCSIZE!" << message;
71#else
72 Q_UNUSED(eventType);
73 Q_UNUSED(message);
74#endif
75
76 return false; // don't accept anything
77 }
78};
79
80DebugAppEventFilter::~DebugAppEventFilter()
81{
82}
83
84DebugWindow::DebugWindow(QWidget *parent)
85 : QWidget(parent)
86 , m_objectViewer(this)
87{
88 // qApp->installNativeEventFilter(new DebugAppEventFilter());
89 auto layout = new QVBoxLayout(this);
90 layout->addWidget(&m_objectViewer);
91
92 auto button = new QPushButton(this);
93 button->setText(QStringLiteral("Dump Debug"));
94 layout->addWidget(button);
95 connect(button, &QPushButton::clicked, this, &DebugWindow::dumpDockWidgetInfo);
96
97 auto hlay = new QHBoxLayout();
98 layout->addLayout(hlay);
99
100 button = new QPushButton(this);
101 auto spin = new QSpinBox(this);
102 spin->setMinimum(0);
103 button->setText(QStringLiteral("Toggle float"));
104 hlay->addWidget(button);
105 hlay->addWidget(spin);
106
107 connect(button, &QPushButton::clicked, this, [spin] {
108 auto docks = DockRegistry::self()->dockwidgets();
109 const int index = spin->value();
110 if (index >= docks.size()) {
111 QMessageBox::warning(nullptr, QStringLiteral("Invalid index"),
112 QStringLiteral("Max index is %1").arg(docks.size() - 1));
113 } else {
114 auto dw = docks.at(index);
115 dw->setFloating(!dw->isFloating());
116 }
117 });
118
119 hlay = new QHBoxLayout();
120 layout->addLayout(hlay);
121 button = new QPushButton(this);
122 auto lineedit = new QLineEdit(this);
123 lineedit->setPlaceholderText(tr("DockWidget unique name"));
124 button->setText(QStringLiteral("Show"));
125 hlay->addWidget(button);
126 hlay->addWidget(lineedit);
127
128 connect(button, &QPushButton::clicked, this, [lineedit] {
129 auto dw = DockRegistry::self()->dockByName(lineedit->text());
130 if (dw) {
131 dw->show();
132 } else {
133 QMessageBox::warning(nullptr, QStringLiteral("Could not find"),
134 QStringLiteral("Could not find DockWidget with name %1").arg(lineedit->text()));
135 }
136 });
137
138 button = new QPushButton(this);
139 button->setText(QStringLiteral("Float all visible docks"));
140 layout->addWidget(button);
141 connect(button, &QPushButton::clicked, this, [] {
142 for (auto dw : DockRegistry::self()->dockwidgets()) {
143 if (dw->isVisible() && !dw->isFloating()) {
144 dw->setFloating(true);
145 }
146 }
147 });
148
149 button = new QPushButton(this);
150 button->setText(QStringLiteral("Show All DockWidgets"));
151 layout->addWidget(button);
152 connect(button, &QPushButton::clicked, this, [this] {
153 QTimer::singleShot(3000, this, [] {
154 const auto docks = DockRegistry::self()->dockwidgets();
155 for (auto dw : docks) {
156 dw->show();
157 }
158 });
159 });
160
161 button = new QPushButton(this);
162 button->setText(QStringLiteral("Save layout"));
163 layout->addWidget(button);
164 connect(button, &QPushButton::clicked, this, [] {
165 LayoutSaver saver;
166 QString message = saver.saveToFile(QStringLiteral("layout.json")) ? QStringLiteral("Saved!")
167 : QStringLiteral("Error!");
168 qDebug() << message;
169 });
170
171 button = new QPushButton(this);
172 button->setText(QStringLiteral("Restore layout"));
173 layout->addWidget(button);
174 connect(button, &QPushButton::clicked, this, [] {
175 LayoutSaver saver;
176 QString message = saver.restoreFromFile(QStringLiteral("layout.json")) ? QStringLiteral("Restored!")
177 : QStringLiteral("Error!");
178 qDebug() << message;
179 });
180
181 button = new QPushButton(this);
182 button->setText(QStringLiteral("Pick Widget"));
183 layout->addWidget(button);
184 connect(button, &QPushButton::clicked, this, [this] {
185 qApp->setOverrideCursor(Qt::CrossCursor);
186 grabMouse();
187
188 QEventLoop loop;
189 m_isPickingWidget = &loop;
190 loop.exec();
191
192 releaseMouse();
193 m_isPickingWidget = nullptr;
194 qApp->restoreOverrideCursor();
195 });
196
197 button = new QPushButton(this);
198 button->setText(QStringLiteral("check sanity"));
199 layout->addWidget(button);
200 connect(button, &QPushButton::clicked, this, [] {
201 const auto mainWindows = DockRegistry::self()->mainwindows();
202 for (MainWindowBase *mainWindow : mainWindows) {
203 mainWindow->layoutWidget()->checkSanity();
204 }
205
206 const auto floatingWindows = DockRegistry::self()->floatingWindows();
207 for (FloatingWindow *floatingWindow : floatingWindows) {
208 floatingWindow->layoutWidget()->checkSanity();
209 }
210 });
211
212 button = new QPushButton(this);
213 button->setText(QStringLiteral("Detach central widget"));
214 layout->addWidget(button);
215 connect(button, &QPushButton::clicked, this, [] {
216 const auto mainWindows = DockRegistry::self()->mainwindows();
217 if (mainWindows.isEmpty())
218 return;
219 auto mainwindow = mainWindows.at(0);
220 auto centralWidget = mainwindow->centralWidget();
221 centralWidget->setParent(nullptr, Qt::Window);
222 if (!centralWidget->isVisible()) {
223 centralWidget->show();
224 }
225 });
226
227 button = new QPushButton(this);
228 button->setText(QStringLiteral("Repaint all widgets"));
229 layout->addWidget(button);
230 connect(button, &QPushButton::clicked, this, [this] {
231 const auto topLevelWidgets = qApp->topLevelWidgets();
232 for (auto w : topLevelWidgets)
233 repaintWidgetRecursive(w);
234 });
235
236 button = new QPushButton(this);
237 button->setText(QStringLiteral("resize by 1x1"));
238 layout->addWidget(button);
239 connect(button, &QPushButton::clicked, this, [] {
240 const auto layouts = DockRegistry::self()->layouts();
241 for (auto l : layouts) {
242 QWidget *tlw = l->window();
243 tlw->resize(tlw->size() + QSize(1, 1));
244 }
245 });
246
247 button = new QPushButton(this);
248 button->setText(QStringLiteral("Raise #0 (after 3s timeout)"));
249 layout->addWidget(button);
250 connect(button, &QPushButton::clicked, this, [this] {
251 QTimer::singleShot(3000, this, [] {
252 const auto docks = DockRegistry::self()->dockwidgets();
253 if (!docks.isEmpty())
254 docks.constFirst()->raise();
255 });
256 });
257
258#ifdef Q_OS_WIN
259 button = new QPushButton(this);
260 button->setText(QStringLiteral("Dump native windows"));
261 layout->addWidget(button);
262 connect(button, &QPushButton::clicked, this, &DebugWindow::dumpWindows);
263#endif
264
265 resize(800, 800);
266}
267
268#ifdef Q_OS_WIN
269void DebugWindow::dumpWindow(QWidget *w)
270{
271 if (w->windowHandle()) {
272 HWND hwnd = HWND(w->winId());
273
274 RECT clientRect;
275 RECT rect;
276 GetWindowRect(hwnd, &rect);
277 GetClientRect(hwnd, &clientRect);
278
279 qDebug() << w
280 << QStringLiteral(" ClientRect=%1,%2 %3x%4").arg(clientRect.left).arg(clientRect.top).arg(clientRect.right - clientRect.left + 1).arg(clientRect.bottom - clientRect.top + 1)
281 << QStringLiteral(" WindowRect=%1,%2 %3x%4").arg(rect.left).arg(rect.top).arg(rect.right - rect.left + 1).arg(rect.bottom - rect.top + 1)
282 << "; geo=" << w->geometry()
283 << "; frameGeo=" << w->frameGeometry();
284 }
285
286 for (QObject *child : w->children()) {
287 if (auto childW = qobject_cast<QWidget *>(child)) {
288 dumpWindow(childW);
289 }
290 }
291}
292
293
294void DebugWindow::dumpWindows()
295{
296 for (QWidget *w : qApp->topLevelWidgets()) {
297 if (w != window())
298 dumpWindow(w);
299 }
300}
301
302#endif
303
304void DebugWindow::repaintWidgetRecursive(QWidget *w)
305{
306 w->repaint();
307 for (QObject *child : w->children()) {
308 if (auto childW = qobject_cast<QWidget *>(child)) {
309 repaintWidgetRecursive(childW);
310 }
311 }
312}
313
314void DebugWindow::dumpDockWidgetInfo()
315{
316 const QVector<FloatingWindow *> floatingWindows = DockRegistry::self()->floatingWindows();
317 const MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
318 const DockWidgetBase::List dockWidgets = DockRegistry::self()->dockwidgets();
319
320 for (FloatingWindow *fw : floatingWindows) {
321 qDebug() << fw << "; affinities=" << fw->affinities();
322 fw->layoutWidget()->dumpLayout();
323 }
324
325 for (MainWindowBase *mw : mainWindows) {
326 qDebug() << mw << "; affinities=" << mw->affinities();
327 mw->layoutWidget()->dumpLayout();
328 }
329
330 for (DockWidgetBase *dw : dockWidgets) {
331 qDebug() << dw << "; affinities=";
332 }
333}
334
335void DebugWindow::mousePressEvent(QMouseEvent *event)
336{
337 if (!m_isPickingWidget)
339
340 QWidget *w = qApp->widgetAt(Qt5Qt6Compat::eventGlobalPos(event));
341 qDebug() << "Widget at pos" << Qt5Qt6Compat::eventGlobalPos(event) << "is"
342 << w << "; parent="
343 << (w ? w->parentWidget() : nullptr) << "; geometry="
344 << (w ? w->geometry() : QRect());
345
346 if (m_isPickingWidget)
347 m_isPickingWidget->quit();
348}
Class to save and restore dockwidget layouts.
QMainWindow sub-class to enable KDDockWidgets support.
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
LayoutSaver allows to save or restore layouts.
Definition LayoutSaver.h:55
bool saveToFile(const QString &jsonFilename)
saves the layout to JSON file
bool restoreFromFile(const QString &jsonFilename)
restores the layout from a JSON file
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
void clicked(bool checked)
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result)=0
int exec(QEventLoop::ProcessEventsFlags flags)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
CrossCursor
virtual void mousePressEvent(QMouseEvent *event)
QWidget * parentWidget() const const
void repaint()
void resize(int w, int h)
WId winId() const const
QWidget * window() const const
QWindow * windowHandle() const const

© 2019-2023 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8