Improved add device wizard

This commit is contained in:
Michael Zanetti 2019-01-09 00:05:33 +01:00
parent 0b0e33a7b5
commit 2740d95e1e
21 changed files with 379 additions and 159 deletions

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea:app *
* *
@ -57,6 +58,10 @@ QVariant DeviceClasses::data(const QModelIndex &index, int role) const
return deviceClass->pluginId().toString();
case RoleVendorId:
return deviceClass->vendorId().toString();
case RoleInterfaces:
return deviceClass->interfaces();
case RoleBaseInterface:
return deviceClass->baseInterface();
}
return QVariant();
}
@ -68,6 +73,9 @@ int DeviceClasses::count() const
DeviceClass *DeviceClasses::get(int index) const
{
if (index < 0 || index >= m_deviceClasses.count()) {
return nullptr;
}
return m_deviceClasses.at(index);
}
@ -108,5 +116,7 @@ QHash<int, QByteArray> DeviceClasses::roleNames() const
roles[RoleDisplayName] = "displayName";
roles[RolePluginId] = "pluginId";
roles[RoleVendorId] = "vendorId";
roles[RoleInterfaces] = "interfaces";
roles[RoleBaseInterface] = "baseInterface";
return roles;
}

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea:app *
* *
@ -37,10 +38,12 @@ public:
RoleName,
RoleDisplayName,
RolePluginId,
RoleVendorId
RoleVendorId,
RoleInterfaces,
RoleBaseInterface
};
explicit DeviceClasses(QObject *parent = 0);
explicit DeviceClasses(QObject *parent = nullptr);
QList<DeviceClass *> deviceClasses();

View File

@ -27,8 +27,10 @@
DeviceClassesProxy::DeviceClassesProxy(QObject *parent) :
QSortFilterProxyModel(parent)
{
setSortRole(DeviceClasses::RoleDisplayName);
}
QUuid DeviceClassesProxy::vendorId() const
{
return m_vendorId;
@ -55,6 +57,35 @@ void DeviceClassesProxy::setDeviceClasses(DeviceClasses *deviceClasses)
m_deviceClasses = deviceClasses;
setSourceModel(deviceClasses);
emit deviceClassesChanged();
sort(0);
}
QString DeviceClassesProxy::filterInterface() const
{
return m_filterInterface;
}
void DeviceClassesProxy::setFilterInterface(const QString &filterInterface)
{
if (m_filterInterface != filterInterface) {
m_filterInterface = filterInterface;
emit filterInterfaceChanged();
invalidateFilter();
}
}
bool DeviceClassesProxy::groupByInterface() const
{
return m_groupByInterface;
}
void DeviceClassesProxy::setGroupByInterface(bool groupByInterface)
{
if (m_groupByInterface != groupByInterface) {
m_groupByInterface = groupByInterface;
emit groupByInterfaceChanged();
invalidate();
}
}
DeviceClass *DeviceClassesProxy::get(int index) const
@ -80,16 +111,27 @@ bool DeviceClassesProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sour
if (deviceClass->createMethods().count() == 1 && deviceClass->createMethods().contains("CreateMethodAuto"))
return false;
if (!m_vendorId.isNull() && deviceClass->vendorId() == m_vendorId)
return true;
if (!m_vendorId.isNull() && deviceClass->vendorId() != m_vendorId)
return false;
return false;
if (!m_filterInterface.isEmpty() && !deviceClass->interfaces().contains(m_filterInterface)) {
return false;
}
return true;
}
bool DeviceClassesProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
QVariant leftName = sourceModel()->data(left);
QVariant rightName = sourceModel()->data(right);
if (m_groupByInterface) {
QString leftBaseInterface = sourceModel()->data(left, DeviceClasses::RoleBaseInterface).toString();
QString rightBaseInterface = sourceModel()->data(right, DeviceClasses::RoleBaseInterface).toString();
if (leftBaseInterface != rightBaseInterface) {
return QString::localeAwareCompare(leftBaseInterface, rightBaseInterface) < 0;
}
}
QString leftName = sourceModel()->data(left, DeviceClasses::RoleDisplayName).toString();
QString rightName = sourceModel()->data(right, DeviceClasses::RoleDisplayName).toString();
return QString::localeAwareCompare(leftName.toString(), rightName.toString()) < 0;
return QString::localeAwareCompare(leftName, rightName) < 0;
}

View File

@ -36,8 +36,12 @@ class DeviceClassesProxy : public QSortFilterProxyModel
Q_PROPERTY(QUuid vendorId READ vendorId WRITE setVendorId NOTIFY vendorIdChanged)
Q_PROPERTY(DeviceClasses *deviceClasses READ deviceClasses WRITE setDeviceClasses NOTIFY deviceClassesChanged)
Q_PROPERTY(QString filterInterface READ filterInterface WRITE setFilterInterface NOTIFY filterInterfaceChanged)
Q_PROPERTY(bool groupByInterface READ groupByInterface WRITE setGroupByInterface NOTIFY groupByInterfaceChanged)
public:
explicit DeviceClassesProxy(QObject *parent = 0);
explicit DeviceClassesProxy(QObject *parent = nullptr);
QUuid vendorId() const;
void setVendorId(const QUuid &vendorId);
@ -45,10 +49,22 @@ public:
DeviceClasses *deviceClasses();
void setDeviceClasses(DeviceClasses *deviceClasses);
QString filterInterface() const;
void setFilterInterface(const QString &filterInterface);
bool groupByInterface() const;
void setGroupByInterface(bool groupByInterface);
Q_INVOKABLE DeviceClass *get(int index) const;
Q_INVOKABLE void resetFilter();
signals:
void vendorIdChanged();
void deviceClassesChanged();
void filterInterfaceChanged();
void groupByInterfaceChanged();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE;
@ -56,11 +72,8 @@ protected:
private:
QUuid m_vendorId;
DeviceClasses *m_deviceClasses;
signals:
void vendorIdChanged();
void deviceClassesChanged();
QString m_filterInterface;
bool m_groupByInterface = false;
};
#endif // DEVICECLASSFILERMODEL_H

View File

@ -74,68 +74,12 @@ QVariant Devices::data(const QModelIndex &index, int role) const
return device->deviceClassId().toString();
case RoleSetupComplete:
return device->setupComplete();
case RoleInterfaces: {
case RoleInterfaces:
return device->deviceClass()->interfaces();
}
case RoleBaseInterface: {
QStringList interfaces = device->deviceClass()->interfaces();
if (interfaces.contains("gateway")) {
return "gateway";
}
if (interfaces.contains("shutter")) {
return "shutter";
}
if (interfaces.contains("blind")) {
return "blind";
}
if (interfaces.contains("garagegate")) {
return "garagegate";
}
if (interfaces.contains("inputtrigger")) {
return "inputtrigger";
}
if (interfaces.contains("awning")) {
return "awning";
}
if (interfaces.contains("outputtrigger")) {
return "outputtrigger";
}
if (interfaces.contains("light")) {
return "light";
}
if (interfaces.contains("sensor")) {
return "sensor";
}
if (interfaces.contains("weather")) {
return "weather";
}
if (interfaces.contains("media")) {
return "media";
}
if (interfaces.contains("button")) {
return "button";
}
if (interfaces.contains("notifications")) {
return "notifications";
}
if (interfaces.contains("smartmeter")) {
return "smartmeter";
}
if (interfaces.contains("heating")) {
return "heating";
}
if (interfaces.contains("evcharger")) {
return "evcharger";
}
if (interfaces.contains("powersocket")) {
return "powersocket";
}
return "uncategorized";
}
case RoleBaseInterface:
return device->deviceClass()->baseInterface();
}
return QVariant();
}
void Devices::addDevice(Device *device)

View File

@ -65,6 +65,20 @@ void InterfacesModel::setShownInterfaces(const QStringList &shownInterfaces)
}
}
bool InterfacesModel::onlyConfiguredDevices() const
{
return m_onlyConfiguredDevices;
}
void InterfacesModel::setOnlyConfiguredDevices(bool onlyConfigured)
{
if (m_onlyConfiguredDevices != onlyConfigured) {
m_onlyConfiguredDevices = onlyConfigured;
emit onlyConfiguredDevicesChanged();
syncInterfaces();
}
}
bool InterfacesModel::showUncategorized() const
{
return m_showUncategorized;
@ -79,30 +93,47 @@ void InterfacesModel::setShowUncategorized(bool showUncategorized)
}
}
QString InterfacesModel::get(int index) const
{
if (index < 0 || index > m_interfaces.count()) {
return QString();
}
return m_interfaces.at(index);
}
void InterfacesModel::syncInterfaces()
{
if (!m_deviceManager) {
return;
}
QStringList baseList;
if (m_onlyConfiguredDevices) {
for (int i = 0; i < m_deviceManager->devices()->rowCount(); i++) {
DeviceClass *dc = m_deviceManager->deviceClasses()->getDeviceClass(m_deviceManager->devices()->get(i)->deviceClassId());
baseList << dc->interfaces();
}
} else {
for (int i = 0; i < m_deviceManager->deviceClasses()->rowCount(); i++) {
DeviceClass *dc = m_deviceManager->deviceClasses()->get(i);
baseList << dc->interfaces();
}
}
baseList.removeDuplicates();
QStringList interfacesInSource;
for (int i = 0; i < m_deviceManager->devices()->rowCount(); i++) {
DeviceClass *dc = m_deviceManager->deviceClasses()->getDeviceClass(m_deviceManager->devices()->get(i)->deviceClassId());
// qDebug() << "device" <<dc->name() << "has interfaces" << dc->interfaces();
bool isInShownIfaces = false;
foreach (const QString &interface, dc->interfaces()) {
if (!m_shownInterfaces.contains(interface)) {
continue;
}
if (!interfacesInSource.contains(interface)) {
interfacesInSource.append(interface);
}
isInShownIfaces = true;
bool isInShownIfaces = false;
foreach (const QString &interface, baseList) {
if (!m_shownInterfaces.contains(interface)) {
continue;
}
if (!isInShownIfaces && !interfacesInSource.contains("uncategorized")) {
interfacesInSource.append("uncategorized");
if (!interfacesInSource.contains(interface)) {
interfacesInSource.append(interface);
}
isInShownIfaces = true;
}
if (!isInShownIfaces && !interfacesInSource.contains("uncategorized")) {
interfacesInSource.append("uncategorized");
}
QStringList interfacesToAdd = interfacesInSource;
QStringList interfacesToRemove;

View File

@ -14,6 +14,8 @@ class InterfacesModel : public QAbstractListModel
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
Q_PROPERTY(DeviceManager* deviceManager READ deviceManager WRITE setDeviceManager NOTIFY deviceManagerChanged)
Q_PROPERTY(QStringList shownInterfaces READ shownInterfaces WRITE setShownInterfaces NOTIFY shownInterfacesChanged)
Q_PROPERTY(bool onlyConfiguredDevices READ onlyConfiguredDevices WRITE setOnlyConfiguredDevices NOTIFY onlyConfiguredDevicesChanged)
Q_PROPERTY(bool showUncategorized READ showUncategorized WRITE setShowUncategorized NOTIFY showUncategorizedChanged)
public:
@ -34,13 +36,19 @@ public:
QStringList shownInterfaces() const;
void setShownInterfaces(const QStringList &shownInterfaces);
bool onlyConfiguredDevices() const;
void setOnlyConfiguredDevices(bool onlyConfigured);
bool showUncategorized() const;
void setShowUncategorized(bool showUncategorized);
Q_INVOKABLE QString get(int index) const;
signals:
void countChanged();
void deviceManagerChanged();
void shownInterfacesChanged();
bool onlyConfiguredDevicesChanged();
void showUncategorizedChanged();
private slots:
@ -52,6 +60,7 @@ private:
QStringList m_interfaces;
QStringList m_shownInterfaces;
bool m_onlyConfiguredDevices = true;
bool m_showUncategorized = false;
};

View File

@ -50,7 +50,7 @@ JsonTypes::JsonTypes(QObject *parent) :
Vendor *JsonTypes::unpackVendor(const QVariantMap &vendorMap)
{
Vendor *v = new Vendor(vendorMap.value("id").toUuid(), vendorMap.value("name").toString());
Vendor *v = new Vendor(vendorMap.value("id").toString(), vendorMap.value("name").toString());
v->setDisplayName(vendorMap.value("displayName").toString());
return v;
}

View File

@ -34,7 +34,7 @@ class VendorsProxy : public QSortFilterProxyModel
Q_PROPERTY(Vendors *vendors READ vendors WRITE setVendors NOTIFY vendorsChanged)
public:
explicit VendorsProxy(QObject *parent = 0);
explicit VendorsProxy(QObject *parent = nullptr);
Vendors *vendors();
void setVendors(Vendors *vendors);

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea:app *
* *
@ -129,6 +130,63 @@ void DeviceClass::setInterfaces(const QStringList &interfaces)
m_interfaces = interfaces;
}
QString DeviceClass::baseInterface() const
{
if (m_interfaces.contains("gateway")) {
return "gateway";
}
if (m_interfaces.contains("shutter")) {
return "shutter";
}
if (m_interfaces.contains("blind")) {
return "blind";
}
if (m_interfaces.contains("garagegate")) {
return "garagegate";
}
if (m_interfaces.contains("inputtrigger")) {
return "inputtrigger";
}
if (m_interfaces.contains("awning")) {
return "awning";
}
if (m_interfaces.contains("outputtrigger")) {
return "outputtrigger";
}
if (m_interfaces.contains("light")) {
return "light";
}
if (m_interfaces.contains("sensor")) {
return "sensor";
}
if (m_interfaces.contains("weather")) {
return "weather";
}
if (m_interfaces.contains("media")) {
return "media";
}
if (m_interfaces.contains("button")) {
return "button";
}
if (m_interfaces.contains("notifications")) {
return "notifications";
}
if (m_interfaces.contains("smartmeter")) {
return "smartmeter";
}
if (m_interfaces.contains("heating")) {
return "heating";
}
if (m_interfaces.contains("evcharger")) {
return "evcharger";
}
if (m_interfaces.contains("powersocket")) {
return "powersocket";
}
return "uncategorized";
}
ParamTypes *DeviceClass::paramTypes() const
{
return m_paramTypes;

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* This file is part of nymea:app *
* *
@ -45,6 +46,7 @@ class DeviceClass : public QObject
Q_PROPERTY(SetupMethod setupMethod READ setupMethod CONSTANT)
Q_PROPERTY(QStringList basicTags READ basicTagNames CONSTANT)
Q_PROPERTY(QStringList interfaces READ interfaces CONSTANT)
Q_PROPERTY(QString baseInterface READ baseInterface CONSTANT)
Q_PROPERTY(ParamTypes *paramTypes READ paramTypes NOTIFY paramTypesChanged)
Q_PROPERTY(ParamTypes *discoveryParamTypes READ discoveryParamTypes NOTIFY discoveryParamTypesChanged)
Q_PROPERTY(StateTypes *stateTypes READ stateTypes NOTIFY stateTypesChanged)
@ -116,6 +118,8 @@ public:
QStringList interfaces() const;
void setInterfaces(const QStringList &interfaces);
QString baseInterface() const;
ParamTypes *paramTypes() const;
void setParamTypes(ParamTypes *paramTypes);

View File

@ -22,19 +22,19 @@
#include "vendor.h"
Vendor::Vendor(const QUuid &id, const QString &name, QObject *parent) :
Vendor::Vendor(const QString &id, const QString &name, QObject *parent) :
QObject(parent),
m_id(id),
m_name(name)
{
}
QUuid Vendor::id() const
QString Vendor::id() const
{
return m_id;
}
void Vendor::setId(const QUuid &id)
void Vendor::setId(const QString &id)
{
m_id = id;
}

View File

@ -32,13 +32,13 @@ class Vendor : public QObject
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString displayName READ displayName CONSTANT)
Q_PROPERTY(QUuid id READ id CONSTANT)
Q_PROPERTY(QString id READ id CONSTANT)
public:
Vendor(const QUuid &id = QUuid(), const QString &name = QString(), QObject *parent = nullptr);
Vendor(const QString &id = QString(), const QString &name = QString(), QObject *parent = nullptr);
QUuid id() const;
void setId(const QUuid &id);
QString id() const;
void setId(const QString &id);
QString name() const;
void setName(const QString &name);
@ -47,7 +47,7 @@ public:
void setDisplayName(const QString &displayName);
private:
QUuid m_id;
QString m_id;
QString m_name;
QString m_displayName;
};

View File

@ -29,24 +29,14 @@ Vendors::Vendors(QObject *parent) :
{
}
QList<Vendor *> Vendors::vendors()
{
return m_vendors;
}
int Vendors::count() const
{
return m_vendors.count();
}
Vendor *Vendors::getVendor(const QUuid &vendorId) const
Vendor *Vendors::getVendor(const QString &vendorId) const
{
foreach (Vendor *vendor, m_vendors) {
if (vendor->id() == vendorId) {
return vendor;
}
}
return 0;
return nullptr;
}
int Vendors::rowCount(const QModelIndex &parent) const
@ -67,7 +57,7 @@ QVariant Vendors::data(const QModelIndex &index, int role) const
case RoleDisplayName:
return vendor->displayName();
case RoleId:
return vendor->id().toString();
return vendor->id();
}
return QVariant();
}
@ -79,15 +69,24 @@ void Vendors::addVendor(Vendor *vendor)
//qDebug() << "Vendors: loaded vendor" << vendor->name();
m_vendors.append(vendor);
endInsertRows();
emit countChanged();
}
void Vendors::clearModel()
{
beginResetModel();
qDebug() << "Vendors: delete all vendors";
qDeleteAll(m_vendors);
m_vendors.clear();
endResetModel();
emit countChanged();
}
Vendor *Vendors::get(int index) const
{
if (index < 0 || index >= m_vendors.count()) {
return nullptr;
}
return m_vendors.at(index);
}
QHash<int, QByteArray> Vendors::roleNames() const

View File

@ -30,6 +30,8 @@
class Vendors : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public:
enum Role {
RoleId,
@ -37,20 +39,20 @@ public:
RoleDisplayName
};
explicit Vendors(QObject *parent = 0);
QList<Vendor *> vendors();
Q_INVOKABLE int count() const;
Q_INVOKABLE Vendor *getVendor(const QUuid &vendorId) const;
explicit Vendors(QObject *parent = nullptr);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
void addVendor(Vendor *vendor);
void clearModel();
Q_INVOKABLE Vendor* get(int index) const;
Q_INVOKABLE Vendor *getVendor(const QString &vendorId) const;
signals:
void countChanged();
protected:
QHash<int, QByteArray> roleNames() const;

View File

@ -32,7 +32,6 @@
<file>ui/components/IconMenuItem.qml</file>
<file>ui/components/Graph.qml</file>
<file>ui/components/ErrorDialog.qml</file>
<file>ui/components/InterfacesModels.qml</file>
<file>ui/components/ShutterControls.qml</file>
<file>ui/components/MeaDialog.qml</file>
<file>ui/components/MeaListItemDelegate.qml</file>
@ -147,5 +146,6 @@
<file>ui/devicepages/BoolSensorDevicePage.qml</file>
<file>ui/devicepages/PowersocketDevicePage.qml</file>
<file>ui/devicelistpages/PowerSocketsDeviceListPage.qml</file>
<file>ui/components/GroupedListView.qml</file>
</qresource>
</RCC>

View File

@ -60,7 +60,7 @@ Page {
Layout.fillWidth: true
}
ListView {
GroupedListView {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
@ -71,11 +71,6 @@ Page {
groupByInterface: true
nameFilter: filterInput.shown ? filterInput.text : ""
}
section.property: "baseInterface"
section.criteria: ViewSection.FullString
section.delegate: ListSectionHeader {
text: app.interfaceToString(section)
}
delegate: ThingDelegate {
device: deviceProxy.get(index)

View File

@ -1,6 +1,7 @@
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import Nymea 1.0
import "components"
import "delegates"
@ -27,7 +28,7 @@ Page {
property DeviceClass deviceClass: null
property DeviceDescriptor deviceDescriptor: null
property var discoveryParams: []
property string deviceName: null
property string deviceName: ""
property int pairRequestId: 0
property var pairingTransactionId: null
property int addRequestId: 0
@ -70,7 +71,12 @@ Page {
StackView {
id: internalPageStack
anchors.fill: parent
initialItem: Page {
Component.onCompleted: push(deviceClassesPage)
}
Component {
id: vendorsPage
Page {
ListView {
anchors.fill: parent
model: VendorsProxy {
@ -92,18 +98,98 @@ Page {
Component {
id: deviceClassesPage
Page {
ListView {
anchors.fill: parent
Pane {
id: filterPane
anchors { left: parent.left; top: parent.top; right: parent.right }
Behavior on height { NumberAnimation { duration: 120; easing.type: Easing.InOutQuad } }
height: implicitHeight + app.margins * 2
Material.elevation: 1
z: 1
leftPadding: 0; rightPadding: 0; topPadding: 0; bottomPadding: 0
contentItem: Rectangle {
color: app.primaryColor
clip: true
GridLayout {
anchors.fill: parent
anchors.margins: app.margins
columnSpacing: app.margins
columns: 2
Label {
text: qsTr("Vendor")
}
ComboBox {
id: vendorFilterComboBox
Layout.fillWidth: true
textRole: "displayName"
model: ListModel {
id: vendorsFilterModel
ListElement { displayName: qsTr("All"); vendorId: "" }
Component.onCompleted: {
for (var i = 0; i < engine.deviceManager.vendors.count; i++) {
var vendor = engine.deviceManager.vendors.get(i);
append({displayName: vendor.displayName, vendorId: vendor.id})
}
}
}
}
Label {
text: qsTr("Type")
}
ComboBox {
id: typeFilterComboBox
Layout.fillWidth: true
textRole: "displayName"
InterfacesModel {
id: interfacesModel
deviceManager: engine.deviceManager
shownInterfaces: app.supportedInterfaces
onlyConfiguredDevices: false
showUncategorized: false
}
model: ListModel {
id: typeFilterModel
ListElement { interfaceName: ""; displayName: qsTr("All") }
Component.onCompleted: {
for (var i = 0; i < interfacesModel.count; i++) {
append({interfaceName: interfacesModel.get(i), displayName: app.interfaceToString(interfacesModel.get(i))});
}
}
}
}
}
}
}
GroupedListView {
anchors {
left: parent.left
top: filterPane.bottom
right: parent.right
bottom: parent.bottom
}
model: DeviceClassesProxy {
id: deviceClassesProxy
vendorId: d.vendorId ? d.vendorId : ""
vendorId: vendorsFilterModel.get(vendorFilterComboBox.currentIndex).vendorId
deviceClasses: engine.deviceManager.deviceClasses
filterInterface: typeFilterModel.get(typeFilterComboBox.currentIndex).interfaceName
groupByInterface: true
}
delegate: MeaListItemDelegate {
id: deviceClassDelegate
width: parent.width
text: model.displayName
subText: engine.deviceManager.vendors.getVendor(model.vendorId).displayName
iconName: app.interfacesToIcon(deviceClass.interfaces)
prominentSubText: false
wrapTexts: false
property var deviceClass: deviceClassesProxy.get(index)
@ -219,23 +305,46 @@ Page {
property var deviceClass: null
ListView {
ColumnLayout {
anchors.fill: parent
model: discovery
delegate: MeaListItemDelegate {
width: parent.width
height: app.delegateHeight
text: model.name
subText: model.description
iconName: app.interfacesToIcon(discoveryView.deviceClass.interfaces)
onClicked: {
d.deviceDescriptor = discovery.get(index);
d.deviceName = model.name;
internalPageStack.push(paramsPage)
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: discovery
delegate: MeaListItemDelegate {
width: parent.width
height: app.delegateHeight
text: model.name
subText: model.description
iconName: app.interfacesToIcon(discoveryView.deviceClass.interfaces)
onClicked: {
d.deviceDescriptor = discovery.get(index);
d.deviceName = model.name;
internalPageStack.push(paramsPage)
}
}
}
Button {
id: retryButton
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
text: qsTr("Search again")
onClicked: discovery.discoverDevices(d.deviceClass.id, d.discoveryParams)
visible: !discovery.busy && discovery.count > 0
}
Button {
id: manualAddButton
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.bottomMargin: app.margins
visible: d.deviceClass.createMethods.indexOf("CreateMethodUser") >= 0
text: qsTr("Add thing manually")
onClicked: internalPageStack.push(paramsPage)
}
}
ColumnLayout {
anchors.centerIn: parent
width: parent.width - app.margins * 2
@ -249,7 +358,6 @@ Page {
}
BusyIndicator {
running: visible
onRunningChanged: print("********* running changed", running)
anchors.horizontalCenter: parent.horizontalCenter
}
}

View File

@ -0,0 +1,15 @@
import QtQuick 2.9
import QtQuick.Controls 2.1
ListView {
ScrollBar.vertical: ScrollBar {}
clip: true
section.property: "baseInterface"
section.criteria: ViewSection.FullString
section.delegate: ListSectionHeader {
text: app.interfaceToString(section)
}
}

View File

@ -1,8 +0,0 @@
import QtQuick 2.0
Item {
property ListModel eventTemplateModel: ListModel {
ListElement { interfaceName: "battery"; stateName: "batteryLevel"; stateDisplayName: qsTr("Battery level"); eventDisplayName: qsTr("Battery level changed") }
ListElement { interfaceName: "battery"; stateName: "batteryCritical"; stateDisplayName: qsTr("Battery critical"); eventDisplayName: qsTr("Battery critical changed") }
}
}

View File

@ -64,16 +64,11 @@ Page {
ThinDivider { visible: root.allowSelectAny }
ListView {
GroupedListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: root.selectInterface ? interfacesProxy : devicesProxy
clip: true
section.property: "baseInterface"
section.criteria: ViewSection.FullString
section.delegate: ListSectionHeader {
text: app.interfaceToString(section)
}
delegate: MeaListItemDelegate {
width: parent.width
text: root.selectInterface ? model.displayName : model.name