From f5a5fb641183d1cc4a74541e98fef5d422c1eb15 Mon Sep 17 00:00:00 2001 From: Krzysztof Date: Thu, 7 Aug 2025 19:22:28 +0200 Subject: [PATCH] Core: Fix 'Expression' and 'Vector' editor outhanging the screen (#22426) * Core: Fix Expression dialog outhanging main window Expression dialog is now fully shown inside main window, even if opened from model panel positioned on right side. If Model panel is outside main window, dialog is opened over this panel. * Core: Fix Vectors dialog outhanging main window Vectors dialog is now fully shown inside main window, even if opened from model panel positioned on right side. If Model panel is outside main window, dialog is opened over this panel. * Core: Simplify 'adjustDialogPosition()' Change suggested and authored by @hyarion --- src/Gui/QuantitySpinBox.cpp | 2 + src/Gui/SpinBox.cpp | 2 + src/Gui/Widgets.cpp | 51 +++++++++++++++++++++++++ src/Gui/Widgets.h | 9 +++++ src/Gui/propertyeditor/PropertyItem.cpp | 1 + 5 files changed, 65 insertions(+) diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index 98749a06b0..b7febd34e6 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -52,6 +52,7 @@ #include "Command.h" #include "Dialogs/DlgExpressionInput.h" #include "Tools.h" +#include "Widgets.h" using namespace Gui; @@ -618,6 +619,7 @@ void QuantitySpinBox::openFormulaDialog() QPoint pos = mapToGlobal(QPoint(0,0)); box->move(pos-box->expressionPosition()); box->setExpressionInputSize(width(), height()); + Gui::adjustDialogPosition(box); Q_EMIT showFormulaDialog(true); } diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index ca0bae7f60..89287b4f54 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -40,6 +40,7 @@ #include "Command.h" #include "Dialogs/DlgExpressionInput.h" #include "QuantitySpinBox_p.h" +#include "Widgets.h" using namespace Gui; @@ -206,6 +207,7 @@ void ExpressionSpinBox::openFormulaDialog() QPoint pos = spinbox->mapToGlobal(QPoint(0,0)); box->move(pos-box->expressionPosition()); box->setExpressionInputSize(spinbox->width(), spinbox->height()); + Gui::adjustDialogPosition(box); } bool ExpressionSpinBox::handleKeyEvent(const QString& text) diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 7bf54da9e9..72920e3ac7 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -55,6 +55,7 @@ #include "QuantitySpinBox_p.h" #include "Tools.h" #include "Dialogs/ui_DlgTreeWidget.h" +#include "MainWindow.h" using namespace Gui; using namespace App; @@ -1606,6 +1607,7 @@ void ExpLineEdit::openFormulaDialog() QPoint pos = mapToGlobal(QPoint(0,0)); box->move(pos-box->expressionPosition()); box->setExpressionInputSize(width(), height()); + Gui::adjustDialogPosition(box); } void ExpLineEdit::finishFormulaDialog() @@ -1663,5 +1665,54 @@ bool ButtonGroup::exclusive() const return _exclusive; } +namespace Gui { + +void adjustDialogPosition(QDialog* dialog) { + if (!dialog) { + return; + } + const MainWindow* mw = getMainWindow(); + if (!mw) { + return; + } + + dialog->adjustSize(); // ensure correct size + + const QRect mainWindowRect{ mw->mapToGlobal(QPoint(0, 0)), mw->size() }; + const QRect dialogRect{ dialog->frameGeometry() }; + + const bool isFullyInside = mainWindowRect.contains(dialogRect); + if (isFullyInside) { + return; + } + + const bool isCompletelyOutside = !mainWindowRect.intersects(dialogRect); + if (isCompletelyOutside) { + return; + } + + const int margin = 5; + const QRect availableArea = mainWindowRect.adjusted( + margin, margin, -margin, -margin + ); + + QPoint adjustedTopLeft = dialogRect.topLeft(); + + adjustedTopLeft.setX(std::clamp( + adjustedTopLeft.x(), + availableArea.left(), + availableArea.right() - dialogRect.width() + )); + + adjustedTopLeft.setY(std::clamp( + adjustedTopLeft.y(), + availableArea.top(), + availableArea.bottom() - dialogRect.height() + )); + + dialog->move(adjustedTopLeft); +} + +} #include "moc_Widgets.cpp" diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h index f086c28f91..34bfe251fe 100644 --- a/src/Gui/Widgets.h +++ b/src/Gui/Widgets.h @@ -613,6 +613,15 @@ private: bool _exclusive; }; +/** + * Adjusts the position of the given dialog to ensure it remains within the bounds of the main window. + * This helps prevent dialogs from appearing partially or fully off-screen relative to the main application window. + * + * This function shall be invoked after the dialog has been shown (using show()) or its position or size has changed. + * Exception: If the dialog is modal, this function should be called before the dialog is called with exec(). + */ +void adjustDialogPosition(QDialog* dialog); + } // namespace Gui #endif // GUI_WIDGETS_H diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 7e0098a46c..c90b4870a6 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -1645,6 +1645,7 @@ void VectorListWidget::buttonClicked() setValue(data); }); + Gui::adjustDialogPosition(dlg); dlg->exec(); }