QmlDesigner: Fix dragging 3D snap configuration spinboxes

Changed to use HelperWidgets.DoubleSpinBox, which has the proper drag
support built into it and implemented required context functions.

Fixes: QDS-10639
Change-Id: I6fce39251d7f754985f95bba5784784fc6eb8fae
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Miikka Heikkinen
2023-09-15 13:24:11 +03:00
parent b73b94d27a
commit f3036d52e5
3 changed files with 100 additions and 47 deletions

View File

@@ -20,13 +20,24 @@ Rectangle {
border.color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
Connections { function handlePosIntChanged() {
target: rootView posIntSpin.value = posInt
}
// Spinboxes lose the initial binding if the value changes so we need these connections function handleRotIntChanged() {
onPosIntChanged: posIntSpin.realValue = rootView.posInt rotIntSpin.value = rotInt
onRotIntChanged: rotIntSpin.realValue = rootView.rotInt }
onScaleIntChanged: scaleIntSpin.realValue = rootView.scaleInt
function handleScaleIntChanged() {
scaleIntSpin.value = scaleInt
}
// Connect context object signals to our handler functions
// Spinboxes lose the initial binding if the value changes so we need these handlers
Component.onCompleted: {
onPosIntChanged.connect(handlePosIntChanged);
onRotIntChanged.connect(handleRotIntChanged);
onScaleIntChanged.connect(handleScaleIntChanged);
} }
ColumnLayout { ColumnLayout {
@@ -94,7 +105,7 @@ Rectangle {
Layout.column: 0 Layout.column: 0
Layout.row: 1 Layout.row: 1
Layout.minimumWidth: 100 Layout.minimumWidth: 100
checked: rootView.posEnabled checked: posEnabled
actionIndicatorVisible: false actionIndicatorVisible: false
hoverEnabled: true hoverEnabled: true
@@ -102,27 +113,26 @@ Rectangle {
ToolTip.text: qsTr("Snap position.") ToolTip.text: qsTr("Snap position.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onToggled: rootView.posEnabled = checked onToggled: posEnabled = checked
} }
StudioControls.RealSpinBox { HelperWidgets.DoubleSpinBox {
id: posIntSpin id: posIntSpin
Layout.fillWidth: true Layout.fillWidth: true
Layout.column: 1 Layout.column: 1
Layout.row: 1 Layout.row: 1
Layout.leftMargin: 10 Layout.leftMargin: 10
realFrom: 1 minimumValue: 1
realTo: 10000 maximumValue: 10000
realValue: rootView.posInt value: posInt
realStepSize: 1 stepSize: 1
actionIndicatorVisible: false decimals: 0
hoverEnabled: true ToolTip.visible: hover
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for move gizmo.") ToolTip.text: qsTr("Snap interval for move gizmo.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.posInt = realValue onValueModified: posInt = value
} }
StudioControls.CheckBox { StudioControls.CheckBox {
@@ -130,7 +140,7 @@ Rectangle {
Layout.column: 0 Layout.column: 0
Layout.row: 2 Layout.row: 2
Layout.minimumWidth: 100 Layout.minimumWidth: 100
checked: rootView.rotEnabled checked: rotEnabled
actionIndicatorVisible: false actionIndicatorVisible: false
hoverEnabled: true hoverEnabled: true
@@ -138,27 +148,26 @@ Rectangle {
ToolTip.text: qsTr("Snap rotation.") ToolTip.text: qsTr("Snap rotation.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onToggled: rootView.rotEnabled = checked onToggled: rotEnabled = checked
} }
StudioControls.RealSpinBox { HelperWidgets.DoubleSpinBox {
id: rotIntSpin id: rotIntSpin
Layout.fillWidth: true Layout.fillWidth: true
Layout.column: 1 Layout.column: 1
Layout.row: 2 Layout.row: 2
Layout.leftMargin: 10 Layout.leftMargin: 10
realFrom: 1 minimumValue: 1
realTo: 90 maximumValue: 90
realValue: rootView.rotInt value: rotInt
realStepSize: 1 stepSize: 1
actionIndicatorVisible: false decimals: 0
hoverEnabled: true ToolTip.visible: hover
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval in degrees for rotation gizmo.") ToolTip.text: qsTr("Snap interval in degrees for rotation gizmo.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.rotInt = realValue onValueModified: rotInt = value
} }
StudioControls.CheckBox { StudioControls.CheckBox {
@@ -166,7 +175,7 @@ Rectangle {
Layout.column: 0 Layout.column: 0
Layout.row: 3 Layout.row: 3
Layout.minimumWidth: 100 Layout.minimumWidth: 100
checked: rootView.scaleEnabled checked: scaleEnabled
actionIndicatorVisible: false actionIndicatorVisible: false
hoverEnabled: true hoverEnabled: true
@@ -174,27 +183,26 @@ Rectangle {
ToolTip.text: qsTr("Snap scale.") ToolTip.text: qsTr("Snap scale.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onToggled: rootView.scaleEnabled = checked onToggled: scaleEnabled = checked
} }
StudioControls.RealSpinBox { HelperWidgets.DoubleSpinBox {
id: scaleIntSpin id: scaleIntSpin
Layout.fillWidth: true Layout.fillWidth: true
Layout.column: 1 Layout.column: 1
Layout.row: 3 Layout.row: 3
Layout.leftMargin: 10 Layout.leftMargin: 10
realFrom: 1 minimumValue: 1
realTo: 100 maximumValue: 100
realValue: rootView.scaleInt value: scaleInt
realStepSize: 1 stepSize: 1
actionIndicatorVisible: false decimals: 0
hoverEnabled: true ToolTip.visible: hover
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for scale gizmo in percentage of original scale.") ToolTip.text: qsTr("Snap interval for scale gizmo in percentage of original scale.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.scaleInt = realValue onValueModified: scaleInt = value
} }
StudioControls.CheckBox { StudioControls.CheckBox {
@@ -204,7 +212,7 @@ Rectangle {
Layout.column: 0 Layout.column: 0
Layout.row: 4 Layout.row: 4
Layout.columnSpan: 3 Layout.columnSpan: 3
checked: rootView.absolute checked: absolute
actionIndicatorVisible: false actionIndicatorVisible: false
hoverEnabled: true hoverEnabled: true
@@ -212,7 +220,7 @@ Rectangle {
ToolTip.text: qsTr("Toggles if the position snaps to absolute values or relative to object position.") ToolTip.text: qsTr("Toggles if the position snaps to absolute values or relative to object position.")
ToolTip.delay: root.toolTipDelay ToolTip.delay: root.toolTipDelay
onToggled: rootView.absolute = checked onToggled: absolute = checked
} }
Text { Text {
@@ -236,7 +244,7 @@ Rectangle {
text: qsTr("Reset All") text: qsTr("Reset All")
Layout.bottomMargin: 8 Layout.bottomMargin: 8
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
onClicked: rootView.resetDefaults() onClicked: resetDefaults()
} }
} }
} }

View File

@@ -11,7 +11,8 @@
#include <utils/environment.h> #include <utils/environment.h>
#include <QPoint> #include <QCursor>
#include <QGuiApplication>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickView> #include <QQuickView>
@@ -69,6 +70,8 @@ void SnapConfiguration::apply()
m_view->syncSnapAuxPropsToSettings(); m_view->syncSnapAuxPropsToSettings();
} }
restoreCursor();
cancel(); cancel();
} }
@@ -83,6 +86,45 @@ void SnapConfiguration::resetDefaults()
setScaleInt(defaultScaleInt); setScaleInt(defaultScaleInt);
} }
void SnapConfiguration::hideCursor()
{
if (QGuiApplication::overrideCursor())
return;
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
if (QWindow *w = QGuiApplication::focusWindow())
m_lastPos = QCursor::pos(w->screen());
}
void SnapConfiguration::restoreCursor()
{
if (!QGuiApplication::overrideCursor())
return;
QGuiApplication::restoreOverrideCursor();
if (QWindow *w = QGuiApplication::focusWindow())
QCursor::setPos(w->screen(), m_lastPos);
}
void SnapConfiguration::holdCursorInPlace()
{
if (!QGuiApplication::overrideCursor())
return;
if (QWindow *w = QGuiApplication::focusWindow())
QCursor::setPos(w->screen(), m_lastPos);
}
int SnapConfiguration::devicePixelRatio()
{
if (QWindow *w = QGuiApplication::focusWindow())
return w->devicePixelRatio();
return 1;
}
void SnapConfiguration::showConfigDialog(const QPoint &pos) void SnapConfiguration::showConfigDialog(const QPoint &pos)
{ {
bool posEnabled = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true).toBool(); bool posEnabled = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true).toBool();
@@ -116,9 +158,7 @@ void SnapConfiguration::showConfigDialog(const QPoint &pos)
m_configDialog->setModality(Qt::NonModal); m_configDialog->setModality(Qt::NonModal);
m_configDialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_configDialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_configDialog->rootContext()->setContextProperties({ m_configDialog->rootContext()->setContextObject(this);
{"rootView", QVariant::fromValue(this)}
});
m_configDialog->setSource(QUrl::fromLocalFile(path)); m_configDialog->setSource(QUrl::fromLocalFile(path));
m_configDialog->installEventFilter(this); m_configDialog->installEventFilter(this);

View File

@@ -5,11 +5,11 @@
#include <auxiliarydata.h> #include <auxiliarydata.h>
#include <QObject> #include <QObject>
#include <QPoint>
#include <QPointer> #include <QPointer>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QQuickView; class QQuickView;
class QPoint;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
@@ -47,6 +47,10 @@ public:
~SnapConfiguration(); ~SnapConfiguration();
Q_INVOKABLE void resetDefaults(); Q_INVOKABLE void resetDefaults();
Q_INVOKABLE void hideCursor();
Q_INVOKABLE void restoreCursor();
Q_INVOKABLE void holdCursorInPlace();
Q_INVOKABLE int devicePixelRatio();
void cancel(); void cancel();
void apply(); void apply();
@@ -98,6 +102,7 @@ private:
double m_rotationInterval = 0.; double m_rotationInterval = 0.;
double m_scaleInterval = 0.; double m_scaleInterval = 0.;
bool m_changes = false; bool m_changes = false;
QPoint m_lastPos;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner