diff options
author | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-01-21 13:34:16 +0200 |
---|---|---|
committer | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-01-28 14:35:17 +0000 |
commit | d5eab1135940531914cdd6a98f5b75efd56c7920 (patch) | |
tree | 09c14cb2630a5c0ddf8c08f63936391cdc5fdd0e | |
parent | 0d3ef2489d9f229c99f3dbcfc58e6029c60fb4a1 (diff) | |
download | qt-creator-d5eab1135940531914cdd6a98f5b75efd56c7920.tar.gz |
QmlDesigner/StateEditor: Improve adding new states
- Added a big add button at the end of the states list.
- Small add states button jumps in (bottom right) when the big button
is out of the view.
- View scrolls to the end when a new slide is added.
Task-number: QDS-5973
Change-Id: Ida96bd663cc0caf32889638fbf4ac9f617916368
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
4 files changed, 110 insertions, 46 deletions
diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml index a047735473..7d0aa14cfd 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml @@ -64,9 +64,6 @@ Rectangle { color: isCurrentState ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlBackgroundInteraction - anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin) - MouseArea { id: mouseArea anchors.fill: parent diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml index 718bbb746f..ef2cbdf62f 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml @@ -26,6 +26,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 +import Qt.labs.qmlmodels 1.0 import HelperWidgets 2.0 import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme @@ -73,9 +74,16 @@ FocusScope { anchors.right: parent.right anchors.rightMargin: 4 anchors.bottom: parent.bottom - anchors.bottomMargin: 4 + scrollBarH - width: 30 - height: 30 + anchors.bottomMargin: statesListView.contentWidth - statesListView.contentX - root.delegateWidth / 2 > statesListView.width ? scrollBarH + 5 : -35 + width: 35 + height: 35 + + Behavior on anchors.bottomMargin { + PropertyAnimation { + duration: 700 + easing.type: Easing.InOutBack + } + } onClicked: root.createNewState() } @@ -93,24 +101,81 @@ FocusScope { orientation: ListView.Horizontal spacing: root.innerSpacing - delegate: StatesDelegate { - id: statesDelegate - width: root.delegateWidth - height: root.delegateHeight - isBaseState: 0 === internalNodeId - isCurrentState: root.currentStateInternalId === internalNodeId - delegateStateName: stateName - delegateStateImageSource: stateImageSource - delegateHasWhenCondition: hasWhenCondition - delegateWhenConditionString: whenConditionString - - topAreaHeight: root.delegateTopAreaHeight - bottomAreaHeight: root.delegateBottomAreaHeight - stateMargin: root.delegateStateMargin - previewMargin: root.delegatePreviewMargin - scrollBarH: root.scrollBarH - listMargin: root.listMargin + property int prevCount: 0 + onCountChanged: { + if (count > prevCount) + Qt.callLater(statesListView.positionViewAtEnd) + prevCount = count + } + + delegate: DelegateChooser { + role: "type" + + DelegateChoice { + roleValue: "state" + + StatesDelegate { + width: root.delegateWidth + height: root.delegateHeight + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin) + isBaseState: 0 === internalNodeId + isCurrentState: root.currentStateInternalId === internalNodeId + delegateStateName: stateName + delegateStateImageSource: stateImageSource + delegateHasWhenCondition: hasWhenCondition + delegateWhenConditionString: whenConditionString + + topAreaHeight: root.delegateTopAreaHeight + bottomAreaHeight: root.delegateBottomAreaHeight + stateMargin: root.delegateStateMargin + previewMargin: root.delegatePreviewMargin + scrollBarH: root.scrollBarH + listMargin: root.listMargin + } + } + + DelegateChoice { + roleValue: "add" + + Rectangle { + visible: canAddNewStates + + width: root.delegateWidth + height: root.delegateHeight + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin) + color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1) + + ToolTip.text: qsTr("Add a new state.") + ToolTip.visible: addState.containsMouse + ToolTip.delay: 1000 + + Rectangle { // inner rect + width: parent.width - 30 + height: parent.height - 30 + anchors.centerIn: parent + color: StudioTheme.Values.themeStateBackground + } + + Text { + text: "+" + anchors.centerIn: parent + anchors.verticalCenterOffset: -5 + font.pixelSize: parent.height * .5 + color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1) + } + + MouseArea { + id: addState + hoverEnabled: true + anchors.fill: parent + onClicked: root.createNewState() + } + } + } } + ScrollBar.horizontal: HorizontalScrollBar {} } } diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp index 1828317a9e..2d96d01a9d 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp @@ -53,7 +53,6 @@ StatesEditorModel::StatesEditorModel(StatesEditorView *view) { } - int StatesEditorModel::count() const { return rowCount(); @@ -64,9 +63,8 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par if (m_statesEditorView.isNull()) return {}; - int internalNodeId = 0; - if (row > 0) + if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state internalNodeId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId(); return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex(); @@ -78,9 +76,9 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const return 0; if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states")) - return 1; + return 2; // base state + add new state - return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 1; + return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state } void StatesEditorModel::reset() @@ -101,16 +99,16 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const switch (role) { case StateNameRole: { - if (index.row() == 0) { - return tr("base state", "Implicit default state"); - } else { - if (stateNode.hasVariantProperty("name")) - return stateNode.variantProperty("name").value(); - else - return QVariant(); - } - + if (index.row() == 0) { + return tr("base state", "Implicit default state"); + } else { + if (stateNode.hasVariantProperty("name")) + return stateNode.variantProperty("name").value(); + else + return QVariant(); } + } + case StateImageSourceRole: { static int randomNumber = 0; randomNumber++; @@ -119,9 +117,12 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const else return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.internalId()).arg(randomNumber); } - case InternalNodeId: return index.internalId(); - case HasWhenCondition: return stateNode.isValid() && stateNode.hasProperty("when"); + case InternalNodeId: + return index.internalId(); + + case HasWhenCondition: + return stateNode.isValid() && stateNode.hasProperty("when"); case WhenConditionString: { if (stateNode.isValid() && stateNode.hasBindingProperty("when")) @@ -137,10 +138,11 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const return false; } - case ModelHasDefaultState: { + case ModelHasDefaultState: return hasDefaultState(); - } + case StateType: + return index.row() == rowCount() - 1 ? "add" : "state"; } return QVariant(); @@ -148,14 +150,15 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const QHash<int, QByteArray> StatesEditorModel::roleNames() const { - static QHash<int, QByteArray> roleNames{ + static QHash<int, QByteArray> roleNames { {StateNameRole, "stateName"}, {StateImageSourceRole, "stateImageSource"}, {InternalNodeId, "internalNodeId"}, {HasWhenCondition, "hasWhenCondition"}, {WhenConditionString, "whenConditionString"}, {IsDefault, "isDefault"}, - {ModelHasDefaultState, "modelHasDefaultState"} + {ModelHasDefaultState, "modelHasDefaultState"}, + {StateType, "type"} }; return roleNames; } @@ -163,10 +166,8 @@ QHash<int, QByteArray> StatesEditorModel::roleNames() const void StatesEditorModel::insertState(int stateIndex) { if (stateIndex >= 0) { - const int updateIndex = stateIndex + 1; beginInsertRows(QModelIndex(), updateIndex, updateIndex); - endInsertRows(); emit dataChanged(index(updateIndex, 0), index(updateIndex, 0)); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h index 65c1385e89..d467e4fceb 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h @@ -44,7 +44,8 @@ class StatesEditorModel : public QAbstractListModel HasWhenCondition, WhenConditionString, IsDefault, - ModelHasDefaultState + ModelHasDefaultState, + StateType }; public: |