forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -64,9 +64,6 @@ Rectangle {
|
|||||||
|
|
||||||
color: isCurrentState ? StudioTheme.Values.themeInteraction
|
color: isCurrentState ? StudioTheme.Values.themeInteraction
|
||||||
: StudioTheme.Values.themeControlBackgroundInteraction
|
: StudioTheme.Values.themeControlBackgroundInteraction
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin)
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
import QtQuickDesignerTheme 1.0
|
import QtQuickDesignerTheme 1.0
|
||||||
|
import Qt.labs.qmlmodels 1.0
|
||||||
import HelperWidgets 2.0
|
import HelperWidgets 2.0
|
||||||
import StudioControls 1.0 as StudioControls
|
import StudioControls 1.0 as StudioControls
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
@@ -73,9 +74,16 @@ FocusScope {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 4
|
anchors.rightMargin: 4
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 4 + scrollBarH
|
anchors.bottomMargin: statesListView.contentWidth - statesListView.contentX - root.delegateWidth / 2 > statesListView.width ? scrollBarH + 5 : -35
|
||||||
width: 30
|
width: 35
|
||||||
height: 30
|
height: 35
|
||||||
|
|
||||||
|
Behavior on anchors.bottomMargin {
|
||||||
|
PropertyAnimation {
|
||||||
|
duration: 700
|
||||||
|
easing.type: Easing.InOutBack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: root.createNewState()
|
onClicked: root.createNewState()
|
||||||
}
|
}
|
||||||
@@ -93,24 +101,81 @@ FocusScope {
|
|||||||
orientation: ListView.Horizontal
|
orientation: ListView.Horizontal
|
||||||
spacing: root.innerSpacing
|
spacing: root.innerSpacing
|
||||||
|
|
||||||
delegate: StatesDelegate {
|
property int prevCount: 0
|
||||||
id: statesDelegate
|
onCountChanged: {
|
||||||
width: root.delegateWidth
|
if (count > prevCount)
|
||||||
height: root.delegateHeight
|
Qt.callLater(statesListView.positionViewAtEnd)
|
||||||
isBaseState: 0 === internalNodeId
|
prevCount = count
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {}
|
ScrollBar.horizontal: HorizontalScrollBar {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,6 @@ StatesEditorModel::StatesEditorModel(StatesEditorView *view)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int StatesEditorModel::count() const
|
int StatesEditorModel::count() const
|
||||||
{
|
{
|
||||||
return rowCount();
|
return rowCount();
|
||||||
@@ -64,9 +63,8 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par
|
|||||||
if (m_statesEditorView.isNull())
|
if (m_statesEditorView.isNull())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
|
||||||
int internalNodeId = 0;
|
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();
|
internalNodeId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId();
|
||||||
|
|
||||||
return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex();
|
return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex();
|
||||||
@@ -78,9 +76,9 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states"))
|
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()
|
void StatesEditorModel::reset()
|
||||||
@@ -101,16 +99,16 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case StateNameRole: {
|
case StateNameRole: {
|
||||||
if (index.row() == 0) {
|
if (index.row() == 0) {
|
||||||
return tr("base state", "Implicit default state");
|
return tr("base state", "Implicit default state");
|
||||||
} else {
|
} else {
|
||||||
if (stateNode.hasVariantProperty("name"))
|
if (stateNode.hasVariantProperty("name"))
|
||||||
return stateNode.variantProperty("name").value();
|
return stateNode.variantProperty("name").value();
|
||||||
else
|
else
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case StateImageSourceRole: {
|
case StateImageSourceRole: {
|
||||||
static int randomNumber = 0;
|
static int randomNumber = 0;
|
||||||
randomNumber++;
|
randomNumber++;
|
||||||
@@ -119,9 +117,12 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
|
|||||||
else
|
else
|
||||||
return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.internalId()).arg(randomNumber);
|
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: {
|
case WhenConditionString: {
|
||||||
if (stateNode.isValid() && stateNode.hasBindingProperty("when"))
|
if (stateNode.isValid() && stateNode.hasBindingProperty("when"))
|
||||||
@@ -137,10 +138,11 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ModelHasDefaultState: {
|
case ModelHasDefaultState:
|
||||||
return hasDefaultState();
|
return hasDefaultState();
|
||||||
}
|
|
||||||
|
|
||||||
|
case StateType:
|
||||||
|
return index.row() == rowCount() - 1 ? "add" : "state";
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -148,14 +150,15 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
QHash<int, QByteArray> StatesEditorModel::roleNames() const
|
QHash<int, QByteArray> StatesEditorModel::roleNames() const
|
||||||
{
|
{
|
||||||
static QHash<int, QByteArray> roleNames{
|
static QHash<int, QByteArray> roleNames {
|
||||||
{StateNameRole, "stateName"},
|
{StateNameRole, "stateName"},
|
||||||
{StateImageSourceRole, "stateImageSource"},
|
{StateImageSourceRole, "stateImageSource"},
|
||||||
{InternalNodeId, "internalNodeId"},
|
{InternalNodeId, "internalNodeId"},
|
||||||
{HasWhenCondition, "hasWhenCondition"},
|
{HasWhenCondition, "hasWhenCondition"},
|
||||||
{WhenConditionString, "whenConditionString"},
|
{WhenConditionString, "whenConditionString"},
|
||||||
{IsDefault, "isDefault"},
|
{IsDefault, "isDefault"},
|
||||||
{ModelHasDefaultState, "modelHasDefaultState"}
|
{ModelHasDefaultState, "modelHasDefaultState"},
|
||||||
|
{StateType, "type"}
|
||||||
};
|
};
|
||||||
return roleNames;
|
return roleNames;
|
||||||
}
|
}
|
||||||
@@ -163,10 +166,8 @@ QHash<int, QByteArray> StatesEditorModel::roleNames() const
|
|||||||
void StatesEditorModel::insertState(int stateIndex)
|
void StatesEditorModel::insertState(int stateIndex)
|
||||||
{
|
{
|
||||||
if (stateIndex >= 0) {
|
if (stateIndex >= 0) {
|
||||||
|
|
||||||
const int updateIndex = stateIndex + 1;
|
const int updateIndex = stateIndex + 1;
|
||||||
beginInsertRows(QModelIndex(), updateIndex, updateIndex);
|
beginInsertRows(QModelIndex(), updateIndex, updateIndex);
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
emit dataChanged(index(updateIndex, 0), index(updateIndex, 0));
|
emit dataChanged(index(updateIndex, 0), index(updateIndex, 0));
|
||||||
|
@@ -44,7 +44,8 @@ class StatesEditorModel : public QAbstractListModel
|
|||||||
HasWhenCondition,
|
HasWhenCondition,
|
||||||
WhenConditionString,
|
WhenConditionString,
|
||||||
IsDefault,
|
IsDefault,
|
||||||
ModelHasDefaultState
|
ModelHasDefaultState,
|
||||||
|
StateType
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Reference in New Issue
Block a user