diff --git a/libnymea-app-core/devices.cpp b/libnymea-app-core/devices.cpp index 62adc069..f9079346 100644 --- a/libnymea-app-core/devices.cpp +++ b/libnymea-app-core/devices.cpp @@ -76,10 +76,58 @@ QVariant Devices::data(const QModelIndex &index, int role) const return device->setupComplete(); case RoleInterfaces: { DeviceClass *dc = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId()); - if (dc) { - return dc->interfaces(); + if (!dc) { + return QVariant(); } + return dc->interfaces(); } + case RoleBaseInterface: { + DeviceClass *dc = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId()); + if (!dc) { + return QVariant(); + } + if (dc->interfaces().contains("gateway")) { + return "gateway"; + } + if (dc->interfaces().contains("shutter")) { + return "shutter"; + } + if (dc->interfaces().contains("blind")) { + return "blind"; + } + if (dc->interfaces().contains("garagegate")) { + return "garagegate"; + } + if (dc->interfaces().contains("inputtrigger")) { + return "inputtrigger"; + } + if (dc->interfaces().contains("awning")) { + return "awning"; + } + if (dc->interfaces().contains("outputtrigger")) { + return "outputtrigger"; + } + if (dc->interfaces().contains("light")) { + return "light"; + } + if (dc->interfaces().contains("sensor")) { + return "sensor"; + } + if (dc->interfaces().contains("weather")) { + return "weather"; + } + if (dc->interfaces().contains("media")) { + return "media"; + } + if (dc->interfaces().contains("button")) { + return "button"; + } + if (dc->interfaces().contains("notifications")) { + return "notifications"; + } + return "uncategorized"; + } + } return QVariant(); @@ -138,5 +186,6 @@ QHash Devices::roleNames() const roles[RoleDeviceClass] = "deviceClassId"; roles[RoleSetupComplete] = "setupComplete"; roles[RoleInterfaces] = "interfaces"; + roles[RoleBaseInterface] = "baseInterface"; return roles; } diff --git a/libnymea-app-core/devices.h b/libnymea-app-core/devices.h index 7d6b7c7d..5d68d42f 100644 --- a/libnymea-app-core/devices.h +++ b/libnymea-app-core/devices.h @@ -38,7 +38,8 @@ public: RoleId, RoleDeviceClass, RoleSetupComplete, - RoleInterfaces + RoleInterfaces, + RoleBaseInterface }; Q_ENUM(Roles) diff --git a/libnymea-app-core/devicesproxy.cpp b/libnymea-app-core/devicesproxy.cpp index 3599502b..e59b3c35 100644 --- a/libnymea-app-core/devicesproxy.cpp +++ b/libnymea-app-core/devicesproxy.cpp @@ -127,6 +127,20 @@ void DevicesProxy::setFilterDisconnected(bool filterDisconnected) } } +bool DevicesProxy::groupByInterface() const +{ + return m_groupByInterface; +} + +void DevicesProxy::setGroupByInterface(bool groupByInterface) +{ + if (m_groupByInterface != groupByInterface) { + m_groupByInterface = groupByInterface; + emit groupByInterfaceChanged(); + invalidate(); + } +} + Device *DevicesProxy::get(int index) const { return getInternal(mapToSource(this->index(index, 0)).row()); @@ -147,10 +161,17 @@ Device *DevicesProxy::getInternal(int source_index) const bool DevicesProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const { - QVariant leftName = sourceModel()->data(left, Devices::RoleName); - QVariant rightName = sourceModel()->data(right, Devices::RoleName); + if (m_groupByInterface) { + QString leftBaseInterface = sourceModel()->data(left, Devices::RoleBaseInterface).toString(); + QString rightBaseInterface = sourceModel()->data(right, Devices::RoleBaseInterface).toString(); + if (leftBaseInterface != rightBaseInterface) { + return QString::localeAwareCompare(leftBaseInterface, rightBaseInterface) < 0; + } + } + QString leftName = sourceModel()->data(left, Devices::RoleName).toString(); + QString rightName = sourceModel()->data(right, Devices::RoleName).toString(); - return QString::localeAwareCompare(leftName.toString(), rightName.toString()) < 0; + return QString::localeAwareCompare(leftName, rightName) < 0; } bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const diff --git a/libnymea-app-core/devicesproxy.h b/libnymea-app-core/devicesproxy.h index 1e68e5a6..68b9142f 100644 --- a/libnymea-app-core/devicesproxy.h +++ b/libnymea-app-core/devicesproxy.h @@ -44,6 +44,8 @@ class DevicesProxy : public QSortFilterProxyModel // Setting this to true will imply filtering for "connectable" interface Q_PROPERTY(bool filterDisconnected READ filterDisconnected WRITE setFilterDisconnected NOTIFY filterDisconnectedChanged) + Q_PROPERTY(bool groupByInterface READ groupByInterface WRITE setGroupByInterface NOTIFY groupByInterfaceChanged) + public: explicit DevicesProxy(QObject *parent = 0); @@ -65,6 +67,9 @@ public: bool filterDisconnected() const; void setFilterDisconnected(bool filterDisconnected); + bool groupByInterface() const; + void setGroupByInterface(bool groupByInterface); + Q_INVOKABLE Device *get(int index) const; signals: @@ -74,6 +79,7 @@ signals: void hiddenInterfacesChanged(); void filterBatteryCriticalChanged(); void filterDisconnectedChanged(); + void groupByInterfaceChanged(); void countChanged(); private: @@ -87,6 +93,8 @@ private: bool m_filterBatteryCritical = false; bool m_filterDisconnected = false; + bool m_groupByInterface = false; + protected: bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; diff --git a/nymea-app/ui/EditDevicesPage.qml b/nymea-app/ui/EditDevicesPage.qml index 5b464a49..5955042c 100644 --- a/nymea-app/ui/EditDevicesPage.qml +++ b/nymea-app/ui/EditDevicesPage.qml @@ -47,15 +47,34 @@ Page { ListView { anchors.fill: parent - model: Engine.deviceManager.devices + model: DevicesProxy { + id: deviceProxy + devices: Engine.deviceManager.devices + groupByInterface: true + } + section.property: "baseInterface" + section.criteria: ViewSection.FullString + section.delegate: ColumnLayout { + width: parent.width + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + text: app.interfaceToString(section) + horizontalAlignment: Text.AlignRight + } + ThinDivider {} + } + delegate: ThingDelegate { - device: Engine.deviceManager.devices.get(index) + device: deviceProxy.get(index) canDelete: true onClicked: { - pageStack.push(Qt.resolvedUrl("devicepages/ConfigureThingPage.qml"), {device: Engine.deviceManager.devices.get(index)}) + pageStack.push(Qt.resolvedUrl("devicepages/ConfigureThingPage.qml"), {device: deviceProxy.get(index)}) } onDeleteClicked: { - d.deviceToRemove = Engine.deviceManager.devices.get(index); + d.deviceToRemove = deviceProxy.get(index); Engine.deviceManager.removeDevice(d.deviceToRemove.id) } }