KDDockWidgets API Documentation  1.5
DebugWindow.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 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 
48 using namespace KDDockWidgets;
49 using namespace KDDockWidgets::Debug;
50 
51 class DebugAppEventFilter : public QAbstractNativeEventFilter
52 {
53 public:
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 
80 DebugAppEventFilter::~DebugAppEventFilter()
81 {
82 }
83 
84 DebugWindow::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
269 void 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 
294 void DebugWindow::dumpWindows()
295 {
296  for (QWidget *w : qApp->topLevelWidgets()) {
297  if (w != window())
298  dumpWindow(w);
299  }
300 }
301 
302 #endif
303 
304 void 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 
314 void 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 
335 void 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 }
QVBoxLayout
QWidget::window
QWidget * window() const const
LayoutSaver.h
Class to save and restore dockwidget layouts.
QLineEdit
QRect
QTimer::singleShot
singleShot
QAbstractButton::clicked
void clicked(bool checked)
QWidget
QSize
QWidget::repaint
void repaint()
QMessageBox::warning
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QEventLoop::exec
int exec(QEventLoop::ProcessEventsFlags flags)
QMouseEvent
Qt::Window
Window
KDDockWidgets::LayoutSaver
LayoutSaver allows to save or restore layouts.
Definition: LayoutSaver.h:55
QSpinBox
QPushButton
QObject
QString
Qt::CrossCursor
CrossCursor
KDDockWidgets::LayoutSaver::restoreFromFile
bool restoreFromFile(const QString &jsonFilename)
restores the layout from a JSON file
Definition: LayoutSaver.cpp:123
QWidget::frameGeometry
frameGeometry
QWidget::resize
void resize(int w, int h)
QWidget::windowHandle
QWindow * windowHandle() const const
MainWindow.h
QMainWindow sub-class to enable KDDockWidgets support.
QHBoxLayout
KDDockWidgets::DockWidgetBase
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
Definition: DockWidgetBase.h:61
KDDockWidgets
Definition: Config.cpp:36
QWidget::winId
WId winId() const const
QWidget::geometry
geometry
KDDockWidgets::LayoutSaver::saveToFile
bool saveToFile(const QString &jsonFilename)
saves the layout to JSON file
Definition: LayoutSaver.cpp:109
KDDockWidgets::MainWindowBase
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
Definition: MainWindowBase.h:56
QVector
QAbstractNativeEventFilter
QEventLoop
QWidget::size
size
QWidget::parentWidget
QWidget * parentWidget() const const
QByteArray
QObject::children
const QObjectList & children() const const
QWidget::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event)

© 2019-2022 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 Mon Mar 7 2022 02:01:20 for KDDockWidgets API Documentation by doxygen 1.8.20