Improved add device wizard
This commit is contained in:
parent
0b0e33a7b5
commit
2740d95e1e
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
15
nymea-app/ui/components/GroupedListView.qml
Normal file
15
nymea-app/ui/components/GroupedListView.qml
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -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") }
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user