QDockWidget has a feature where you can double click on the title bar and the dock will toggle to a floating window and back to its docked state. The problem is if you move and resize the floating window and then toggle back to the dock and then back to floating again, your position and size are lost.
I've looked for solutions to resize and move a QDockWidget and I've taken a look at the Qt source code for QDockWidget. I've created a small subclass of QDockWidget that appears to solve the problem. It overrides the mouseDoubleClick, resize and move events, filtering out the unwanted "random" resizing and positioning by Qt and stores the information about screen, position and size in a struct that I store in QSettings for persistence between sessions.
// header
#include <QDockWidget>
#include "global.h"
class DockWidget : public QDockWidget
{
Q_OBJECT
public:
DockWidget(const QString &title, QWidget *parent = nullptr);
QSize sizeHint() const;
void rpt(QString s);
struct DWLoc {
int screen;
QPoint pos;
QSize size;
};
DWLoc dw;
bool ignore;
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
void moveEvent(QMoveEvent *event);
};
// cpp
#include "dockwidget.h"
DockWidget::DockWidget(const QString &title, QWidget *parent)
: QDockWidget(title, parent)
{
ignore = false;
}
bool DockWidget::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick) {
ignore = true;
setFloating(!isFloating());
if (isFloating()) {
// move and size to previous state
QRect screenres = QApplication::desktop()->screenGeometry(dw.screen);
move(QPoint(screenres.x() + dw.pos.x(), screenres.y() + dw.pos.y()));
ignore = false;
adjustSize();
}
ignore = false;
return true;
}
QDockWidget::event(event);
return true;
}
void DockWidget::resizeEvent(QResizeEvent *event)
{
if (ignore) {
return;
}
if (isFloating()) {
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = event->size();
}
}
QSize DockWidget::sizeHint() const
{
return dw.size;
}
void DockWidget::moveEvent(QMoveEvent *event)
{
if (ignore || !isFloating()) return;
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = QSize(r.width(), r.height());
}
While this appears to be working is there a simpler way to accomplish this? What do I do if a QDockWidget was on a screen that is now turned off?