Gui: enable dock/undock/fullscreen for all MDI widgets

This commit is contained in:
jffmichi
2025-07-01 20:29:50 +02:00
parent ef9378bd5b
commit 05045d6f10
8 changed files with 209 additions and 190 deletions

View File

@@ -25,6 +25,7 @@
#ifndef _PreComp_
# include <boost/signals2.hpp>
# include <boost/core/ignore_unused.hpp>
# include <QAction>
# include <QApplication>
# include <QEvent>
# include <QCloseEvent>
@@ -129,6 +130,11 @@ void MDIView::deleteSelf()
_pcDocument = nullptr;
}
MDIView* MDIView::clone()
{
return nullptr;
}
PyObject* MDIView::getPyObject()
{
if (!pythonObject)
@@ -207,7 +213,7 @@ bool MDIView::canClose()
return true;
}
void MDIView::closeEvent(QCloseEvent *e)
void MDIView::closeEvent(QCloseEvent* e)
{
if (canClose()) {
e->accept();
@@ -353,7 +359,8 @@ QSize MDIView::minimumSizeHint () const
return {400, 300};
}
void MDIView::changeEvent(QEvent *e)
void MDIView::changeEvent(QEvent* e)
{
switch (e->type()) {
case QEvent::ActivationChange:
@@ -377,6 +384,29 @@ void MDIView::changeEvent(QEvent *e)
}
}
bool MDIView::eventFilter(QObject* watched, QEvent* event)
{
// As long as this widget is a top-level window (either in 'TopLevel' or 'FullScreen' mode) we
// need to be notified when an action is added to a widget. This action must also be added to
// this window to allow one to make use of its shortcut (if defined).
// Note: We don't need to care about removing an action if its parent widget gets destroyed.
// This does the action itself for us.
if (watched != this && event->type() == QEvent::ActionAdded) {
auto actionEvent = static_cast<QActionEvent*>(event);
QAction* action = actionEvent->action();
if (!action->isSeparator()) {
QList<QAction*> acts = actions();
if (!acts.contains(action)) {
addAction(action);
}
}
}
return false;
}
#if defined(Q_WS_X11)
// To fix bug #0000345 move function declaration to here
extern void qt_x11_wait_for_window_manager( QWidget* w ); // defined in qwidget_x11.cpp
@@ -384,36 +414,43 @@ extern void qt_x11_wait_for_window_manager( QWidget* w ); // defined in qwidget_
void MDIView::setCurrentViewMode(ViewMode mode)
{
ViewMode oldmode = MDIView::currentViewMode();
if (oldmode == mode) {
return;
}
switch (mode) {
// go to normal mode
case Child:
{
if (this->currentMode == FullScreen) {
if (currentMode == FullScreen) {
showNormal();
setWindowFlags(windowFlags() & ~Qt::Window);
}
else if (this->currentMode == TopLevel) {
this->wstate = windowState();
else if (currentMode == TopLevel) {
wstate = windowState();
setWindowFlags( windowFlags() & ~Qt::Window );
}
if (this->currentMode != Child) {
this->currentMode = Child;
if (currentMode != Child) {
currentMode = Child;
getMainWindow()->addWindow(this);
getMainWindow()->activateWindow();
update();
}
} break;
// go to top-level mode
case TopLevel:
{
if (this->currentMode == Child) {
if (qobject_cast<QMdiSubWindow*>(this->parentWidget()))
getMainWindow()->removeWindow(this,false);
if (currentMode == Child) {
if (qobject_cast<QMdiSubWindow*>(parentWidget()))
getMainWindow()->removeWindow(this, false);
setWindowFlags(windowFlags() | Qt::Window);
setParent(nullptr, Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
Qt::WindowMinMaxButtonsHint);
if (this->wstate & Qt::WindowMaximized)
setParent(nullptr,
Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowMinMaxButtonsHint);
if (wstate & Qt::WindowMaximized)
showMaximized();
else
showNormal();
@@ -424,35 +461,64 @@ void MDIView::setCurrentViewMode(ViewMode mode)
#endif
activateWindow();
}
else if (this->currentMode == FullScreen) {
if (this->wstate & Qt::WindowMaximized)
else if (currentMode == FullScreen) {
if (wstate & Qt::WindowMaximized)
showMaximized();
else
showNormal();
}
this->currentMode = TopLevel;
currentMode = TopLevel;
update();
} break;
// go to fullscreen mode
case FullScreen:
{
if (this->currentMode == Child) {
if (qobject_cast<QMdiSubWindow*>(this->parentWidget()))
getMainWindow()->removeWindow(this,false);
if (currentMode == Child) {
if (qobject_cast<QMdiSubWindow*>(parentWidget()))
getMainWindow()->removeWindow(this, false);
setWindowFlags(windowFlags() | Qt::Window);
setParent(nullptr, Qt::Window);
showFullScreen();
}
else if (this->currentMode == TopLevel) {
this->wstate = windowState();
else if (currentMode == TopLevel) {
wstate = windowState();
showFullScreen();
}
this->currentMode = FullScreen;
currentMode = FullScreen;
update();
} break;
}
if (oldmode == Child) {
// To make a global shortcut working from this window we need to add
// all existing actions from the mainwindow and its sub-widgets
QList<QAction*> acts = getMainWindow()->findChildren<QAction*>();
addActions(acts);
// To be notfified for new actions
qApp->installEventFilter(this);
}
else if (mode == Child) {
qApp->removeEventFilter(this);
QList<QAction*> acts = actions();
for (QAction* it : acts) {
removeAction(it);
}
// When switching from undocked to docked mode, the widget position is somehow not updated
// correctly. In this case mapToGlobal(Point()) returns {0, 0} even though the widget is
// clearly not at the top-left corner of the screen. We fix this by briefly changing the
// maximum size of the widget.
const auto oldsize = maximumSize();
setMaximumSize({1, 1});
setMaximumSize(oldsize);
}
}
QString MDIView::buildWindowTitle() const