diff --git a/nymea-app/configuredhostsmodel.cpp b/nymea-app/configuredhostsmodel.cpp
index 04ed7ce6..6a2c973b 100644
--- a/nymea-app/configuredhostsmodel.cpp
+++ b/nymea-app/configuredhostsmodel.cpp
@@ -115,6 +115,20 @@ void ConfiguredHostsModel::removeHost(int index)
}
}
+void ConfiguredHostsModel::move(int from, int to)
+{
+ // QList's and QAbstractItemModel's move implementation differ when moving an item up the list :/
+ // While QList needs the index in the resulting list, beginMoveRows expects it to be in the current list
+ // adjust the model's index by +1 in case we're moving upwards
+ int newModelIndex = to > from ? to+1 : to;
+
+ qWarning() << "from:" << from << "to" << to << "modelTo" << newModelIndex;
+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), newModelIndex);
+ m_list.move(from, to);
+ saveToDisk();
+ endMoveRows();
+}
+
int ConfiguredHostsModel::indexOf(ConfiguredHost *host) const
{
return m_list.indexOf(host);
diff --git a/nymea-app/configuredhostsmodel.h b/nymea-app/configuredhostsmodel.h
index 64890775..e24ab108 100644
--- a/nymea-app/configuredhostsmodel.h
+++ b/nymea-app/configuredhostsmodel.h
@@ -60,6 +60,7 @@ public:
Q_INVOKABLE ConfiguredHost* get(int index) const;
Q_INVOKABLE ConfiguredHost* createHost();
Q_INVOKABLE void removeHost(int index);
+ Q_INVOKABLE void move(int from, int to);
signals:
void countChanged();
diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc
index 4979d230..20c1f0a8 100644
--- a/nymea-app/images.qrc
+++ b/nymea-app/images.qrc
@@ -304,5 +304,6 @@
ui/images/sensors/window-open.svg
ui/images/infinity.svg
ui/images/edit-paste.svg
+ ui/images/list-move.svg
diff --git a/nymea-app/ui/MainMenu.qml b/nymea-app/ui/MainMenu.qml
index 4657edac..326a00ac 100644
--- a/nymea-app/ui/MainMenu.qml
+++ b/nymea-app/ui/MainMenu.qml
@@ -33,6 +33,7 @@ Drawer {
spacing: 0
Rectangle {
+ id: upperPart
Layout.fillWidth: true
Layout.preferredHeight: topSectionLayout.implicitHeight
color: Qt.tint(Style.backgroundColor, Qt.rgba(Style.foregroundColor.r, Style.foregroundColor.g, Style.foregroundColor.b, 0.05))
@@ -66,21 +67,31 @@ Drawer {
}
}
-
- Repeater {
+ ListView {
+ id: hostsListView
+ Layout.fillWidth: true
+ Layout.preferredHeight: count * Style.smallDelegateHeight
model: root.configuredHosts
+ clip: true
+ interactive: false
+ moveDisplaced: Transition {
+ NumberAnimation { property: "y"; duration: Style.animationDuration; easing.type: Easing.InOutQuad }
+ }
+
delegate: NymeaItemDelegate {
id: hostDelegate
+ width: hostsListView.width
+ visible: !dndArea.dragging || dndArea.draggedIndex !== index
readonly property ConfiguredHost configuredHost: root.configuredHosts.get(index)
- Layout.fillWidth: true
text: model.name.length > 0 ? model.name : qsTr("New connection")
subText: configuredHost.engine.jsonRpcClient.currentConnection ? configuredHost.engine.jsonRpcClient.currentConnection.url : ""
prominentSubText: false
progressive: false
additionalItem: RowLayout {
anchors.verticalCenter: parent.verticalCenter
+ visible: !dndArea.dragging
Rectangle {
height: Style.smallIconSize
width: height
@@ -97,7 +108,7 @@ Drawer {
onClicked: {
tokenSettings.setValue(hostDelegate.configuredHost.uuid, "")
configuredHostsModel.removeHost(index)
- }
+ }
Settings {
id: tokenSettings
@@ -105,26 +116,94 @@ Drawer {
}
}
}
- onClicked: {
- if (topSectionLayout.configureConnections) {
- var nymeaHost = nymeaDiscovery.nymeaHosts.find(hostDelegate.configuredHost.uuid);
- if (nymeaHost) {
- var connectionInfoDialog = Qt.createComponent("/ui/components/ConnectionInfoDialog.qml")
- var popup = connectionInfoDialog.createObject(app,{nymeaEngine: configuredHost.engine, nymeaHost: nymeaHost})
- popup.open()
- popup.connectionSelected.connect(function(connection) {
- print("...")
- configuredHost.engine.jsonRpcClient.disconnectFromHost();
- configuredHost.engine.jsonRpcClient.connectToHost(nymeaHost, connection)
- configuredHostsModel.currentIndex = index
- root.close()
- })
+
+ MouseArea {
+ anchors.fill: parent
+
+ onClicked: {
+ if (topSectionLayout.configureConnections) {
+ var nymeaHost = nymeaDiscovery.nymeaHosts.find(hostDelegate.configuredHost.uuid);
+ if (nymeaHost) {
+ var connectionInfoDialog = Qt.createComponent("/ui/components/ConnectionInfoDialog.qml")
+ var popup = connectionInfoDialog.createObject(app,{nymeaEngine: configuredHost.engine, nymeaHost: nymeaHost})
+ popup.open()
+ popup.connectionSelected.connect(function(connection) {
+ print("...")
+ configuredHost.engine.jsonRpcClient.disconnectFromHost();
+ configuredHost.engine.jsonRpcClient.connectToHost(nymeaHost, connection)
+ configuredHostsModel.currentIndex = index
+ root.close()
+ })
+ }
+ } else {
+ configuredHostsModel.currentIndex = index
+ root.close()
}
- } else {
- configuredHostsModel.currentIndex = index
- root.close()
}
}
+
+ }
+
+ NymeaItemDelegate {
+ id: fakeDragItem
+ visible: dndArea.dragging
+ width: hostsListView.width
+ prominentSubText: false
+ progressive: false
+ background: Rectangle {
+ color: Style.tileBackgroundColor
+ }
+ additionalItem: ColorIcon {
+ anchors.verticalCenter: parent.verticalCenter
+ size: Style.iconSize
+ name: "list-move"
+ }
+ }
+
+ MouseArea {
+ id: dndArea
+ anchors.fill: parent
+ propagateComposedEvents: true
+ preventStealing: dragging
+ property int draggedIndex: -1
+ property bool dragging: false
+ property int startY: 0
+ property int originY: 0
+
+ onPressed: {
+ startY = mouseY
+ }
+
+ onPressAndHold: {
+ draggedIndex = hostsListView.indexAt(mouseX, startY)
+ var draggedItem = hostsListView.itemAt(mouseX, startY)
+ fakeDragItem.text = draggedItem.text
+ fakeDragItem.subText = draggedItem.subText
+ fakeDragItem.y = draggedItem.y
+ originY = draggedItem.y
+ dragging = true
+ }
+
+ onMouseYChanged: {
+ if (!dragging) {
+ return;
+ }
+ var diff = startY - mouseY
+ fakeDragItem.y = Math.max(0, Math.min(hostsListView.height - fakeDragItem.height, originY - diff))
+
+ var hoveredIdx = hostsListView.indexAt(mouseX, mouseY)
+ if (hoveredIdx >= 0 && draggedIndex != hoveredIdx) {
+ print("moved", draggedIndex, "to", hoveredIdx)
+ root.configuredHosts.move(draggedIndex, hoveredIdx)
+ draggedIndex = hoveredIdx;
+ }
+ }
+
+ onReleased: {
+ dragging = false
+ }
+
+
}
}
@@ -148,6 +227,7 @@ Drawer {
}
}
+
Flickable {
Layout.fillWidth: true
Layout.fillHeight: true
@@ -181,8 +261,8 @@ Drawer {
iconName: "../images/magic.svg"
progressive: false
visible: root.currentEngine && root.currentEngine.jsonRpcClient.currentHost
- && NymeaUtils.hasPermissionScope(root.currentEngine.jsonRpcClient.permissions, UserInfo.PermissionScopeConfigureRules)
- && root.currentEngine.jsonRpcClient.connected && Configuration.magicEnabled
+ && NymeaUtils.hasPermissionScope(root.currentEngine.jsonRpcClient.permissions, UserInfo.PermissionScopeConfigureRules)
+ && root.currentEngine.jsonRpcClient.connected && Configuration.magicEnabled
onClicked: {
root.openMagicSettings();
root.close();
@@ -252,11 +332,11 @@ Drawer {
}
}
-// Component {
-// id: hostConnectionInfoComponent
-// MeaDialog {
+ // Component {
+ // id: hostConnectionInfoComponent
+ // MeaDialog {
-// }
-// }
+ // }
+ // }
}
diff --git a/nymea-app/ui/images/list-move.svg b/nymea-app/ui/images/list-move.svg
new file mode 100644
index 00000000..afef27d1
--- /dev/null
+++ b/nymea-app/ui/images/list-move.svg
@@ -0,0 +1,187 @@
+
+
+
+