BrowserItemActions
This commit is contained in:
parent
2ad624329c
commit
41ebfb48f3
@ -314,7 +314,7 @@ void DeviceManager::editDeviceResponse(const QVariantMap ¶ms)
|
||||
|
||||
void DeviceManager::executeActionResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
// qDebug() << "Execute Action response" << params;
|
||||
qDebug() << "Execute Action response" << params;
|
||||
emit executeActionReply(params);
|
||||
}
|
||||
|
||||
@ -428,15 +428,15 @@ int DeviceManager::executeAction(const QUuid &deviceId, const QUuid &actionTypeI
|
||||
return m_jsonClient->sendCommand("Actions.ExecuteAction", p, this, "executeActionResponse");
|
||||
}
|
||||
|
||||
BrowserItems *DeviceManager::browseDevice(const QUuid &deviceId, const QString &nodeId)
|
||||
BrowserItems *DeviceManager::browseDevice(const QUuid &deviceId, const QString &itemId)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", deviceId.toString());
|
||||
params.insert("nodeId", nodeId);
|
||||
params.insert("itemId", itemId);
|
||||
int id = m_jsonClient->sendCommand("Devices.BrowseDevice", params, this, "browseDeviceResponse");
|
||||
|
||||
// Intentionally not parented. The caller takes ownership and needs to destroy when not needed any more.
|
||||
BrowserItems *itemModel = new BrowserItems();
|
||||
BrowserItems *itemModel = new BrowserItems(deviceId, itemId);
|
||||
itemModel->setBusy(true);
|
||||
QPointer<BrowserItems> itemModelPtr(itemModel);
|
||||
m_browsingRequests.insert(id, itemModelPtr);
|
||||
@ -444,6 +444,19 @@ BrowserItems *DeviceManager::browseDevice(const QUuid &deviceId, const QString &
|
||||
return itemModel;
|
||||
}
|
||||
|
||||
void DeviceManager::refreshBrowserItems(BrowserItems *browserItems)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", browserItems->deviceId().toString());
|
||||
params.insert("itemId", browserItems->itemId());
|
||||
int id = m_jsonClient->sendCommand("Devices.BrowseDevice", params, this, "browseDeviceResponse");
|
||||
|
||||
// Intentionally not parented. The caller takes ownership and needs to destroy when not needed any more.
|
||||
browserItems->setBusy(true);
|
||||
QPointer<BrowserItems> itemModelPtr(browserItems);
|
||||
m_browsingRequests.insert(id, browserItems);
|
||||
}
|
||||
|
||||
void DeviceManager::browseDeviceResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Browsing response:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
|
||||
@ -459,33 +472,68 @@ void DeviceManager::browseDeviceResponse(const QVariantMap ¶ms)
|
||||
return;
|
||||
}
|
||||
|
||||
QList<BrowserItem*> itemsToRemove = itemModel->list();
|
||||
|
||||
|
||||
foreach (const QVariant &itemVariant, params.value("params").toMap().value("items").toList()) {
|
||||
QVariantMap itemMap = itemVariant.toMap();
|
||||
BrowserItem *item = new BrowserItem(itemMap.value("id").toString(), this);
|
||||
QString itemId = itemMap.value("id").toString();
|
||||
BrowserItem *item = itemModel->getBrowserItem(itemId);
|
||||
if (!item) {
|
||||
item = new BrowserItem(itemId, this);
|
||||
itemModel->addBrowserItem(item);
|
||||
}
|
||||
item->setDisplayName(itemMap.value("displayName").toString());
|
||||
item->setDescription(itemMap.value("description").toString());
|
||||
item->setIcon(itemMap.value("icon").toString());
|
||||
item->setThumbnail(itemMap.value("thumbnail").toString());
|
||||
item->setExecutable(itemMap.value("executable").toBool());
|
||||
item->setBrowsable(itemMap.value("browsable").toBool());
|
||||
item->setDisabled(itemMap.value("disabled").toBool());
|
||||
item->setActionTypeIds(itemMap.value("actionTypeIds").toStringList());
|
||||
|
||||
item->setMediaIcon(itemMap.value("mediaIcon").toString());
|
||||
itemModel->addBrowserItem(item);
|
||||
|
||||
if (itemsToRemove.contains(item)) {
|
||||
itemsToRemove.removeAll(item);
|
||||
}
|
||||
}
|
||||
|
||||
while (!itemsToRemove.isEmpty()) {
|
||||
BrowserItem *item = itemsToRemove.takeFirst();
|
||||
itemModel->removeItem(item);
|
||||
}
|
||||
|
||||
itemModel->setBusy(false);
|
||||
}
|
||||
|
||||
void DeviceManager::executeBrowserItem(const QUuid &deviceId, const QString &nodeId)
|
||||
int DeviceManager::executeBrowserItem(const QUuid &deviceId, const QString &itemId)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", deviceId);
|
||||
params.insert("nodeId", nodeId);
|
||||
m_jsonClient->sendCommand("Devices.ExecuteBrowserItem", params, this, "executeBrowserItemResponse");
|
||||
params.insert("itemId", itemId);
|
||||
return m_jsonClient->sendCommand("Actions.ExecuteBrowserItem", params, this, "executeBrowserItemResponse");
|
||||
}
|
||||
|
||||
void DeviceManager::executeBrowserItemResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Execute Browser Item finished" << params;
|
||||
emit executeBrowserItemReply(params);
|
||||
}
|
||||
|
||||
int DeviceManager::executeBrowserItemAction(const QUuid &deviceId, const QString &itemId, const QUuid &actionTypeId, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap data;
|
||||
data.insert("deviceId", deviceId);
|
||||
data.insert("itemId", itemId);
|
||||
data.insert("actionTypeId", actionTypeId);
|
||||
data.insert("params", params);
|
||||
return m_jsonClient->sendCommand("Actions.ExecuteBrowserItemAction", data, this, "executeBrowserItemActionResponse");
|
||||
}
|
||||
|
||||
void DeviceManager::executeBrowserItemActionResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Execute Browser Item Action finished" << params;
|
||||
emit executeBrowserItemActionReply(params);
|
||||
}
|
||||
|
||||
|
||||
@ -74,8 +74,10 @@ public:
|
||||
Q_INVOKABLE void reconfigureDevice(const QUuid &deviceId, const QVariantList &deviceParams);
|
||||
Q_INVOKABLE void reconfigureDiscoveredDevice(const QUuid &deviceId, const QUuid &deviceDescriptorId);
|
||||
Q_INVOKABLE int executeAction(const QUuid &deviceId, const QUuid &actionTypeId, const QVariantList ¶ms = QVariantList());
|
||||
Q_INVOKABLE BrowserItems* browseDevice(const QUuid &deviceId, const QString &nodeId = QString());
|
||||
Q_INVOKABLE void executeBrowserItem(const QUuid &deviceId, const QString &nodeId);
|
||||
Q_INVOKABLE BrowserItems* browseDevice(const QUuid &deviceId, const QString &itemId = QString());
|
||||
Q_INVOKABLE void refreshBrowserItems(BrowserItems *browserItems);
|
||||
Q_INVOKABLE int executeBrowserItem(const QUuid &deviceId, const QString &itemId);
|
||||
Q_INVOKABLE int executeBrowserItemAction(const QUuid &deviceId, const QString &itemId, const QUuid &actionTypeId, const QVariantMap ¶ms = QVariantMap());
|
||||
|
||||
private:
|
||||
Q_INVOKABLE void notificationReceived(const QVariantMap &data);
|
||||
@ -94,6 +96,7 @@ private:
|
||||
Q_INVOKABLE void reconfigureDeviceResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void browseDeviceResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void executeBrowserItemResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void executeBrowserItemActionResponse(const QVariantMap ¶ms);
|
||||
|
||||
public slots:
|
||||
void savePluginConfig(const QUuid &pluginId);
|
||||
@ -107,6 +110,8 @@ signals:
|
||||
void editDeviceReply(const QVariantMap ¶ms);
|
||||
void reconfigureDeviceReply(const QVariantMap ¶ms);
|
||||
void executeActionReply(const QVariantMap ¶ms);
|
||||
void executeBrowserItemReply(const QVariantMap ¶ms);
|
||||
void executeBrowserItemActionReply(const QVariantMap ¶ms);
|
||||
void fetchingDataChanged();
|
||||
void notificationReceived(const QString &deviceId, const QString &eventTypeId, const QVariantList ¶ms);
|
||||
|
||||
|
||||
@ -127,6 +127,13 @@ DeviceClass *JsonTypes::unpackDeviceClass(const QVariantMap &deviceClassMap, QOb
|
||||
}
|
||||
deviceClass->setActionTypes(actionTypes);
|
||||
|
||||
// BrowserItemActionTypes
|
||||
ActionTypes *browserItemActionTypes = new ActionTypes(deviceClass);
|
||||
foreach (QVariant actionType, deviceClassMap.value("browserItemActionTypes").toList()) {
|
||||
browserItemActionTypes->addActionType(JsonTypes::unpackActionType(actionType.toMap(), actionTypes));
|
||||
}
|
||||
deviceClass->setBrowserItemActionTypes(browserItemActionTypes);
|
||||
|
||||
return deviceClass;
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,10 @@ QString BrowserItem::displayName() const
|
||||
|
||||
void BrowserItem::setDisplayName(const QString &displayName)
|
||||
{
|
||||
m_displayName = displayName;
|
||||
if (m_displayName != displayName) {
|
||||
m_displayName = displayName;
|
||||
emit displayNameChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString BrowserItem::description() const
|
||||
@ -29,7 +32,10 @@ QString BrowserItem::description() const
|
||||
|
||||
void BrowserItem::setDescription(const QString &description)
|
||||
{
|
||||
m_description = description;
|
||||
if (m_description != description) {
|
||||
m_description = description;
|
||||
emit descriptionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString BrowserItem::icon() const
|
||||
@ -39,7 +45,10 @@ QString BrowserItem::icon() const
|
||||
|
||||
void BrowserItem::setIcon(const QString &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
if (m_icon != icon) {
|
||||
m_icon = icon;
|
||||
emit iconChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString BrowserItem::thumbnail() const
|
||||
@ -49,7 +58,10 @@ QString BrowserItem::thumbnail() const
|
||||
|
||||
void BrowserItem::setThumbnail(const QString &thumbnail)
|
||||
{
|
||||
m_thumbnail = thumbnail;
|
||||
if (m_thumbnail != thumbnail) {
|
||||
m_thumbnail = thumbnail;
|
||||
emit thumbnailChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserItem::executable() const
|
||||
@ -59,7 +71,10 @@ bool BrowserItem::executable() const
|
||||
|
||||
void BrowserItem::setExecutable(bool executable)
|
||||
{
|
||||
m_executable = executable;
|
||||
if (m_executable != executable) {
|
||||
m_executable = executable;
|
||||
emit executableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserItem::browsable() const
|
||||
@ -69,7 +84,36 @@ bool BrowserItem::browsable() const
|
||||
|
||||
void BrowserItem::setBrowsable(bool browsable)
|
||||
{
|
||||
m_browsable = browsable;
|
||||
if (m_browsable != browsable) {
|
||||
m_browsable = browsable;
|
||||
emit browsableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserItem::disabled() const
|
||||
{
|
||||
return m_disabled;
|
||||
}
|
||||
|
||||
void BrowserItem::setDisabled(bool disabled)
|
||||
{
|
||||
if (m_disabled != disabled) {
|
||||
m_disabled = disabled;
|
||||
emit disabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList BrowserItem::actionTypeIds() const
|
||||
{
|
||||
return m_actionTypeIds;
|
||||
}
|
||||
|
||||
void BrowserItem::setActionTypeIds(const QStringList &actionTypeIds)
|
||||
{
|
||||
if (m_actionTypeIds != actionTypeIds) {
|
||||
m_actionTypeIds = actionTypeIds;
|
||||
emit actionTypeIdsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString BrowserItem::mediaIcon() const
|
||||
@ -79,5 +123,8 @@ QString BrowserItem::mediaIcon() const
|
||||
|
||||
void BrowserItem::setMediaIcon(const QString &mediaIcon)
|
||||
{
|
||||
m_mediaIcon = mediaIcon;
|
||||
if (m_mediaIcon != mediaIcon) {
|
||||
m_mediaIcon = mediaIcon;
|
||||
emit mediaIconChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,14 +8,16 @@ class BrowserItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid id READ id CONSTANT)
|
||||
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
||||
Q_PROPERTY(QString description READ description CONSTANT)
|
||||
Q_PROPERTY(QString icon READ icon CONSTANT)
|
||||
Q_PROPERTY(QString thumbnail READ thumbnail CONSTANT)
|
||||
Q_PROPERTY(bool executable READ executable CONSTANT)
|
||||
Q_PROPERTY(bool browsable READ browsable CONSTANT)
|
||||
Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
|
||||
Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
|
||||
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
|
||||
Q_PROPERTY(QString thumbnail READ thumbnail NOTIFY thumbnailChanged)
|
||||
Q_PROPERTY(bool executable READ executable NOTIFY executableChanged)
|
||||
Q_PROPERTY(bool browsable READ browsable NOTIFY browsableChanged)
|
||||
Q_PROPERTY(bool disabled READ disabled NOTIFY disabledChanged)
|
||||
Q_PROPERTY(QStringList actionTypeIds READ actionTypeIds NOTIFY actionTypeIdsChanged)
|
||||
|
||||
Q_PROPERTY(QString mediaIcon READ mediaIcon CONSTANT)
|
||||
Q_PROPERTY(QString mediaIcon READ mediaIcon NOTIFY mediaIconChanged)
|
||||
|
||||
public:
|
||||
explicit BrowserItem(const QString &id, QObject *parent = nullptr);
|
||||
@ -40,9 +42,27 @@ public:
|
||||
bool browsable() const;
|
||||
void setBrowsable(bool browsable);
|
||||
|
||||
bool disabled() const;
|
||||
void setDisabled(bool disabled);
|
||||
|
||||
QStringList actionTypeIds() const;
|
||||
void setActionTypeIds(const QStringList &actionTypeIds);
|
||||
|
||||
QString mediaIcon() const;
|
||||
void setMediaIcon(const QString &mediaIcon);
|
||||
|
||||
signals:
|
||||
void displayNameChanged();
|
||||
void descriptionChanged();
|
||||
void iconChanged();
|
||||
void thumbnailChanged();
|
||||
void executableChanged();
|
||||
void browsableChanged();
|
||||
void disabledChanged();
|
||||
void actionTypeIdsChanged();
|
||||
|
||||
void mediaIconChanged();
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
@ -51,6 +71,8 @@ private:
|
||||
QString m_thumbnail;
|
||||
bool m_executable = false;
|
||||
bool m_browsable = false;
|
||||
bool m_disabled = false;
|
||||
QStringList m_actionTypeIds;
|
||||
|
||||
QString m_mediaIcon;
|
||||
};
|
||||
|
||||
@ -3,7 +3,10 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
BrowserItems::BrowserItems(QObject *parent): QAbstractListModel(parent)
|
||||
BrowserItems::BrowserItems(const QUuid &deviceId, const QString &itemId, QObject *parent):
|
||||
QAbstractListModel (parent),
|
||||
m_deviceId(deviceId),
|
||||
m_itemId(itemId)
|
||||
{
|
||||
|
||||
}
|
||||
@ -13,6 +16,16 @@ BrowserItems::~BrowserItems()
|
||||
qDebug() << "Deleting BrowserItems";
|
||||
}
|
||||
|
||||
QUuid BrowserItems::deviceId() const
|
||||
{
|
||||
return m_deviceId;
|
||||
}
|
||||
|
||||
QString BrowserItems::itemId() const
|
||||
{
|
||||
return m_itemId;
|
||||
}
|
||||
|
||||
bool BrowserItems::busy() const
|
||||
{
|
||||
return m_busy;
|
||||
@ -41,6 +54,10 @@ QVariant BrowserItems::data(const QModelIndex &index, int role) const
|
||||
return m_list.at(index.row())->executable();
|
||||
case RoleBrowsable:
|
||||
return m_list.at(index.row())->browsable();
|
||||
case RoleActionTypeIds:
|
||||
return m_list.at(index.row())->actionTypeIds();
|
||||
case RoleDisabled:
|
||||
return m_list.at(index.row())->disabled();
|
||||
|
||||
case RoleMediaIcon:
|
||||
return m_list.at(index.row())->mediaIcon();
|
||||
@ -58,6 +75,8 @@ QHash<int, QByteArray> BrowserItems::roleNames() const
|
||||
roles.insert(RoleThumbnail, "thumbnail");
|
||||
roles.insert(RoleExecutable, "executable");
|
||||
roles.insert(RoleBrowsable, "browsable");
|
||||
roles.insert(RoleDisabled, "disabled");
|
||||
roles.insert(RoleActionTypeIds, "actionTypeIds");
|
||||
|
||||
roles.insert(RoleMediaIcon, "mediaIcon");
|
||||
return roles;
|
||||
@ -72,6 +91,22 @@ void BrowserItems::addBrowserItem(BrowserItem *browserItem)
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void BrowserItems::removeItem(BrowserItem *browserItem)
|
||||
{
|
||||
int idx = m_list.indexOf(browserItem);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
m_list.takeAt(idx)->deleteLater();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QList<BrowserItem *> BrowserItems::list() const
|
||||
{
|
||||
return m_list;
|
||||
}
|
||||
|
||||
void BrowserItems::setBusy(bool busy)
|
||||
{
|
||||
if (m_busy != busy) {
|
||||
@ -79,3 +114,21 @@ void BrowserItems::setBusy(bool busy)
|
||||
emit busyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
BrowserItem *BrowserItems::get(int index) const
|
||||
{
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_list.at(index);
|
||||
}
|
||||
|
||||
BrowserItem *BrowserItems::getBrowserItem(const QString &itemId)
|
||||
{
|
||||
foreach (BrowserItem *item, m_list) {
|
||||
if (item->id() == itemId) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define BROWSERITEMS_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QUuid>
|
||||
|
||||
class BrowserItem;
|
||||
|
||||
@ -19,14 +20,19 @@ public:
|
||||
RoleThumbnail,
|
||||
RoleBrowsable,
|
||||
RoleExecutable,
|
||||
RoleDisabled,
|
||||
RoleActionTypeIds,
|
||||
|
||||
RoleMediaIcon,
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit BrowserItems(QObject *parent = nullptr);
|
||||
explicit BrowserItems(const QUuid &deviceId, const QString &itemId, QObject *parent = nullptr);
|
||||
virtual ~BrowserItems() override;
|
||||
|
||||
QUuid deviceId() const;
|
||||
QString itemId() const;
|
||||
|
||||
bool busy() const;
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
@ -34,10 +40,14 @@ public:
|
||||
virtual QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
virtual void addBrowserItem(BrowserItem *browserItem);
|
||||
|
||||
void removeItem(BrowserItem *browserItem);
|
||||
|
||||
QList<BrowserItem*> list() const;
|
||||
void setBusy(bool busy);
|
||||
|
||||
// Q_INVOKABLE virtual BrowserItem* get(int index) const;
|
||||
// Q_INVOKABLE virtual BrowserItem* getBrowserItem(const QString &itemId);
|
||||
Q_INVOKABLE virtual BrowserItem* get(int index) const;
|
||||
Q_INVOKABLE virtual BrowserItem* getBrowserItem(const QString &itemId);
|
||||
|
||||
// void clear();
|
||||
|
||||
@ -48,6 +58,9 @@ signals:
|
||||
protected:
|
||||
bool m_busy = false;
|
||||
QList<BrowserItem*> m_list;
|
||||
|
||||
QUuid m_deviceId;
|
||||
QString m_itemId;
|
||||
};
|
||||
|
||||
#endif // BROWSERITEMS_H
|
||||
|
||||
@ -261,6 +261,20 @@ void DeviceClass::setActionTypes(ActionTypes *actionTypes)
|
||||
emit actionTypesChanged();
|
||||
}
|
||||
|
||||
ActionTypes *DeviceClass::browserItemActionTypes() const
|
||||
{
|
||||
return m_browserItemActionTypes;
|
||||
}
|
||||
|
||||
void DeviceClass::setBrowserItemActionTypes(ActionTypes *browserActionTypes)
|
||||
{
|
||||
if (m_browserItemActionTypes) {
|
||||
m_browserItemActionTypes->deleteLater();
|
||||
}
|
||||
m_browserItemActionTypes = browserActionTypes;
|
||||
emit browserItemActionTypesChanged();
|
||||
}
|
||||
|
||||
bool DeviceClass::hasActionType(const QString &actionTypeId)
|
||||
{
|
||||
foreach (ActionType *actionType, m_actionTypes->actionTypes()) {
|
||||
|
||||
@ -53,6 +53,7 @@ class DeviceClass : public QObject
|
||||
Q_PROPERTY(StateTypes *stateTypes READ stateTypes NOTIFY stateTypesChanged)
|
||||
Q_PROPERTY(EventTypes *eventTypes READ eventTypes NOTIFY eventTypesChanged)
|
||||
Q_PROPERTY(ActionTypes *actionTypes READ actionTypes NOTIFY actionTypesChanged)
|
||||
Q_PROPERTY(ActionTypes *browserItemActionTypes READ browserItemActionTypes NOTIFY browserItemActionTypesChanged)
|
||||
|
||||
public:
|
||||
|
||||
@ -113,8 +114,20 @@ public:
|
||||
ActionTypes *actionTypes() const;
|
||||
void setActionTypes(ActionTypes *actionTypes);
|
||||
|
||||
ActionTypes *browserItemActionTypes() const;
|
||||
void setBrowserItemActionTypes(ActionTypes *browserActionTypes);
|
||||
|
||||
Q_INVOKABLE bool hasActionType(const QString &actionTypeId);
|
||||
|
||||
signals:
|
||||
void paramTypesChanged();
|
||||
void settingsTypesChanged();
|
||||
void discoveryParamTypesChanged();
|
||||
void stateTypesChanged();
|
||||
void eventTypesChanged();
|
||||
void actionTypesChanged();
|
||||
void browserItemActionTypesChanged();
|
||||
|
||||
private:
|
||||
QUuid m_id;
|
||||
QUuid m_vendorId;
|
||||
@ -132,13 +145,6 @@ private:
|
||||
StateTypes *m_stateTypes = nullptr;
|
||||
EventTypes *m_eventTypes = nullptr;
|
||||
ActionTypes *m_actionTypes = nullptr;
|
||||
|
||||
signals:
|
||||
void paramTypesChanged();
|
||||
void settingsTypesChanged();
|
||||
void discoveryParamTypesChanged();
|
||||
void stateTypesChanged();
|
||||
void eventTypesChanged();
|
||||
void actionTypesChanged();
|
||||
ActionTypes *m_browserItemActionTypes = nullptr;
|
||||
};
|
||||
#endif // DEVICECLASS_H
|
||||
|
||||
@ -26,6 +26,8 @@ RowLayout {
|
||||
imageSource: "../images/media-skip-backward.svg"
|
||||
longpressImageSource: "../images/media-seek-backward.svg"
|
||||
enabled: root.playbackState.value !== "Stopped"
|
||||
opacity: enabled ? 1 : .5
|
||||
|
||||
repeat: true
|
||||
onClicked: {
|
||||
root.executeAction("skipBack")
|
||||
@ -61,6 +63,7 @@ RowLayout {
|
||||
imageSource: "../images/media-skip-forward.svg"
|
||||
longpressImageSource: "../images/media-seek-forward.svg"
|
||||
enabled: root.playbackState.value !== "Stopped"
|
||||
opacity: enabled ? 1 : .5
|
||||
repeat: true
|
||||
onClicked: {
|
||||
root.executeAction("skipNext")
|
||||
|
||||
@ -3,10 +3,9 @@ import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Material 2.1
|
||||
|
||||
ToolBar {
|
||||
Item {
|
||||
id: root
|
||||
Material.elevation: 1
|
||||
|
||||
implicitHeight: toolBar.implicitHeight + infoPane.height
|
||||
property string text
|
||||
property alias backButtonVisible: backButton.visible
|
||||
property alias menuButtonVisible: menuButton.visible
|
||||
@ -15,33 +14,103 @@ ToolBar {
|
||||
signal backPressed();
|
||||
signal menuPressed();
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
anchors { fill: parent; leftMargin: app.margins; rightMargin: app.margins }
|
||||
function showInfo(text, isError, isSticky) {
|
||||
if (isError === undefined) isError = false;
|
||||
if (isSticky === undefined) isSticky = false;
|
||||
|
||||
HeaderButton {
|
||||
id: menuButton
|
||||
objectName: "headerMenuButton"
|
||||
imageSource: "../images/navigation-menu.svg"
|
||||
visible: false
|
||||
onClicked: root.menuPressed();
|
||||
}
|
||||
infoPane.text = text;
|
||||
infoPane.isError = isError;
|
||||
infoPane.isSticky = isSticky;
|
||||
|
||||
HeaderButton {
|
||||
id: backButton
|
||||
objectName: "backButton"
|
||||
imageSource: "../images/back.svg"
|
||||
onClicked: root.backPressed();
|
||||
}
|
||||
Label {
|
||||
id: label
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: app.mediumFont
|
||||
elide: Text.ElideRight
|
||||
text: root.text
|
||||
color: app.headerForegroundColor
|
||||
if (!isSticky) {
|
||||
infoPaneTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
ToolBar {
|
||||
id: toolBar
|
||||
Material.elevation: 3
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
anchors { fill: parent; leftMargin: app.margins; rightMargin: app.margins }
|
||||
|
||||
HeaderButton {
|
||||
id: menuButton
|
||||
objectName: "headerMenuButton"
|
||||
imageSource: "../images/navigation-menu.svg"
|
||||
visible: false
|
||||
onClicked: root.menuPressed();
|
||||
}
|
||||
|
||||
HeaderButton {
|
||||
id: backButton
|
||||
objectName: "backButton"
|
||||
imageSource: "../images/back.svg"
|
||||
onClicked: root.backPressed();
|
||||
}
|
||||
Label {
|
||||
id: label
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: app.mediumFont
|
||||
elide: Text.ElideRight
|
||||
text: root.text
|
||||
color: app.headerForegroundColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
id: infoPane
|
||||
Material.elevation: 1
|
||||
|
||||
property string text
|
||||
property bool isError: false
|
||||
property bool isSticky: false
|
||||
property bool shown: isSticky || infoPaneTimer.running
|
||||
|
||||
visible: height > 0
|
||||
height: shown ? contentRow.implicitHeight : 0
|
||||
Behavior on height { NumberAnimation {} }
|
||||
anchors { left: parent.left; top: toolBar.bottom; right: parent.right }
|
||||
|
||||
padding: 0
|
||||
contentItem: Rectangle {
|
||||
color: infoPane.isError ? "red" : app.accentColor
|
||||
implicitHeight: contentRow.implicitHeight
|
||||
RowLayout {
|
||||
id: contentRow
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right; leftMargin: app.margins; rightMargin: app.margins }
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
height: app.iconSize
|
||||
}
|
||||
|
||||
Label {
|
||||
text: infoPane.text
|
||||
visible: infoPane.alertState
|
||||
font.pixelSize: app.smallFont
|
||||
color: "white"
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
height: app.iconSize / 2
|
||||
width: height
|
||||
visible: true
|
||||
color: "white"
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: infoPaneTimer
|
||||
interval: 5000
|
||||
repeat: false
|
||||
running: false
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ SwipeDelegate {
|
||||
|
||||
property alias additionalItem: additionalItemContainer.children
|
||||
|
||||
property alias busy: busyIndicator.running
|
||||
|
||||
signal deleteClicked()
|
||||
|
||||
contentItem: RowLayout {
|
||||
@ -52,6 +54,13 @@ SwipeDelegate {
|
||||
color: root.iconColor
|
||||
visible: root.fallbackIcon && (!root.iconName || icon.status === Image.Error)
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: busyIndicator
|
||||
anchors.centerIn: parent
|
||||
visible: running
|
||||
running: false
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
@ -14,157 +14,189 @@ DeviceListPageBase {
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
ListView {
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
model: root.devicesProxy
|
||||
contentHeight: contentGrid.implicitHeight
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: itemDelegate
|
||||
GridLayout {
|
||||
id: contentGrid
|
||||
width: parent.width
|
||||
columns: Math.ceil(width / 500)
|
||||
rowSpacing: 0
|
||||
columnSpacing: 0
|
||||
|
||||
property bool inline: width > 500
|
||||
Repeater {
|
||||
model: root.devicesProxy
|
||||
|
||||
property Device device: devicesProxy.get(index);
|
||||
property DeviceClass deviceClass: device.deviceClass
|
||||
delegate: ItemDelegate {
|
||||
id: itemDelegate
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
|
||||
readonly property StateType playbackStateType: deviceClass.stateTypes.findByName("playbackStatus")
|
||||
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
|
||||
property bool inline: width > 500
|
||||
|
||||
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||
contentItem: Pane {
|
||||
id: contentItem
|
||||
Material.elevation: 2
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
property Device device: devicesProxy.get(index);
|
||||
property DeviceClass deviceClass: device.deviceClass
|
||||
|
||||
contentItem: ItemDelegate {
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: app.mediumFont + app.margins
|
||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
|
||||
RowLayout {
|
||||
anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: parent.right; margins: app.margins }
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/battery/battery-020.svg"
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
||||
}
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
||||
color: "red"
|
||||
}
|
||||
}
|
||||
readonly property StateType playbackStateType: deviceClass.stateTypes.findByName("playbackStatus")
|
||||
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
|
||||
|
||||
}
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
id: leftColummn
|
||||
Layout.margins: app.margins
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.playbackState.value === "Stopped" ?
|
||||
qsTr("No playback")
|
||||
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
// font.pixelSize: app.largeFont
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("artist").id).value
|
||||
font.pixelSize: app.smallFont
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("collection").id).value
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: app.smallFont
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
MediaControls {
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("mediacontroller") >= 0
|
||||
device: itemDelegate.device
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.preferredHeight: leftColummn.height + app.margins * 2
|
||||
Layout.preferredWidth: height * .7
|
||||
readonly property StateType playerTypeStateType: deviceClass.stateTypes.findByName("playerType")
|
||||
readonly property State playerTypeState: playerTypeStateType ? device.states.getState(playerTypeStateType.id) : null
|
||||
|
||||
Item {
|
||||
id: artworkContainer
|
||||
anchors.fill: parent
|
||||
Image {
|
||||
id: artworkImage
|
||||
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
|
||||
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
|
||||
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
|
||||
source: artworkState ? artworkState.value : ""
|
||||
}
|
||||
}
|
||||
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||
contentItem: Pane {
|
||||
id: contentItem
|
||||
Material.elevation: 2
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
contentItem: ItemDelegate {
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Rectangle {
|
||||
id: maskRect
|
||||
anchors.centerIn: parent
|
||||
height: parent.width
|
||||
width: parent.height
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0; color: "transparent" }
|
||||
GradientStop { position: 1; color: "red" }
|
||||
}
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
anchors.fill: parent
|
||||
property variant source: ShaderEffectSource {
|
||||
sourceItem: artworkContainer
|
||||
hideSource: true
|
||||
}
|
||||
property variant mask: ShaderEffectSource {
|
||||
sourceItem: maskRect
|
||||
hideSource: true
|
||||
}
|
||||
|
||||
fragmentShader: "
|
||||
varying highp vec2 qt_TexCoord0;
|
||||
uniform sampler2D source;
|
||||
uniform sampler2D mask;
|
||||
void main(void)
|
||||
{
|
||||
highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
|
||||
highp float alpha = texture2D(mask, vec2(qt_TexCoord0.y, qt_TexCoord0.x)).a;
|
||||
sourceColor *= alpha;
|
||||
gl_FragColor = sourceColor;
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: app.mediumFont + app.margins
|
||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
|
||||
RowLayout {
|
||||
anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: parent.right; margins: app.margins }
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
"
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/battery/battery-020.svg"
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
||||
}
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
||||
color: "red"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
id: leftColummn
|
||||
Layout.margins: app.margins
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.playbackState.value === "Stopped" ?
|
||||
qsTr("No playback")
|
||||
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
// font.pixelSize: app.largeFont
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("artist").id).value
|
||||
font.pixelSize: app.smallFont
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("collection").id).value
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: app.smallFont
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
MediaControls {
|
||||
visible: itemDelegate.deviceClass.interfaces.indexOf("mediacontroller") >= 0
|
||||
device: itemDelegate.device
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.preferredHeight: leftColummn.height + app.margins * 2
|
||||
Layout.preferredWidth: height * .7
|
||||
|
||||
Item {
|
||||
id: artworkContainer
|
||||
anchors.fill: parent
|
||||
Image {
|
||||
id: artworkImage
|
||||
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
|
||||
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
|
||||
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
|
||||
source: artworkState ? artworkState.value : ""
|
||||
}
|
||||
Rectangle {
|
||||
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
width: Math.min(parent.width, parent.height) - app.margins * 2
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
name: itemDelegate.playerTypeState && itemDelegate.playerTypeState.value === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg"
|
||||
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: maskRect
|
||||
anchors.centerIn: parent
|
||||
height: parent.width
|
||||
width: parent.height
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0; color: "#00FF0000" }
|
||||
GradientStop { position: 0.2; color: "#15FF0000" }
|
||||
GradientStop { position: 1; color: "#FFFF0000" }
|
||||
}
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
anchors.fill: parent
|
||||
property variant source: ShaderEffectSource {
|
||||
sourceItem: artworkContainer
|
||||
hideSource: true
|
||||
}
|
||||
property variant mask: ShaderEffectSource {
|
||||
sourceItem: maskRect
|
||||
hideSource: true
|
||||
}
|
||||
|
||||
fragmentShader: "
|
||||
varying highp vec2 qt_TexCoord0;
|
||||
uniform sampler2D source;
|
||||
uniform sampler2D mask;
|
||||
void main(void)
|
||||
{
|
||||
highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
|
||||
highp float alpha = texture2D(mask, vec2(qt_TexCoord0.y, qt_TexCoord0.x)).a;
|
||||
sourceColor *= alpha;
|
||||
gl_FragColor = sourceColor;
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
enterPage(index, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
enterPage(index, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,9 +17,40 @@ Page {
|
||||
d.model = engine.deviceManager.browseDevice(root.device.id, root.nodeId);
|
||||
}
|
||||
|
||||
function executeBrowserItem(itemId) {
|
||||
d.pendingItemId = itemId
|
||||
d.pendingBrowserItemId = engine.deviceManager.executeBrowserItem(root.device.id, itemId)
|
||||
}
|
||||
function executeBrowserItemAction(itemId, actionTypeId, params) {
|
||||
d.pendingItemId = itemId
|
||||
d.pendingBrowserItemId = engine.deviceManager.executeBrowserItemAction(root.device.id, itemId, actionTypeId, params)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property BrowserItems model: null
|
||||
property int pendingBrowserItemId: -1
|
||||
property string pendingItemId: ""
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.deviceManager
|
||||
onExecuteBrowserItemReply: actionExecuted(params)
|
||||
onExecuteBrowserItemActionReply: actionExecuted(params)
|
||||
}
|
||||
function actionExecuted(params) {
|
||||
print("Execute Action reply:", params, params.id, params["id"], d.pendingBrowserItemId)
|
||||
if (params.id === d.pendingBrowserItemId) {
|
||||
d.pendingBrowserItemId = -1;
|
||||
d.pendingItemId = ""
|
||||
print("yep finished")
|
||||
if (params.status !== "success") {
|
||||
header.showInfo(params.error, true);
|
||||
} else if (params.params.deviceError !== "DeviceErrorNoError") {
|
||||
header.showInfo(qsTr("Error: %1").arg(params.params.deviceError), true)
|
||||
}
|
||||
}
|
||||
engine.deviceManager.refreshBrowserItems(d.model)
|
||||
}
|
||||
|
||||
ListView {
|
||||
@ -36,16 +67,25 @@ Page {
|
||||
prominentSubText: false
|
||||
iconName: model.thumbnail
|
||||
fallbackIcon: "../images/browser/" + model.icon + ".svg"
|
||||
enabled: model.browsable || model.executable
|
||||
enabled: !model.disabled
|
||||
busy: d.pendingItemId === model.id
|
||||
|
||||
onClicked: {
|
||||
print("clicked:", model.id)
|
||||
if (model.executable) {
|
||||
engine.deviceManager.executeBrowserItem(root.device.id, model.id)
|
||||
root.executeBrowserItem(model.id)
|
||||
} else if (model.browsable) {
|
||||
pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device, nodeId: model.id})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onPressAndHold: {
|
||||
print("show actions:", model.actionTypeIds)
|
||||
var popup = actionDialogComponent.createObject(this, {title: model.displayName, itemId: model.id, actionTypeIds: model.actionTypeIds});
|
||||
popup.open()
|
||||
// root.device.deviceClass.browserItemActionTypes.getActionType()
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
@ -55,4 +95,32 @@ Page {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: actionDialogComponent
|
||||
MeaDialog {
|
||||
id: actionDialog
|
||||
|
||||
property string itemId
|
||||
property alias actionTypeIds: actionListView.model
|
||||
|
||||
ListView {
|
||||
id: actionListView
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: count * 50
|
||||
interactive: contentHeight > height
|
||||
clip: true
|
||||
delegate: NymeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: actionType.displayName
|
||||
progressive: false
|
||||
property ActionType actionType: root.device.deviceClass.browserItemActionTypes.getActionType(modelData)
|
||||
onClicked: {
|
||||
var params = []
|
||||
root.executeBrowserItemAction(actionDialog.itemId, actionType.id, params)
|
||||
actionDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,12 @@ DevicePageBase {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.deviceClass.browsable && playbackState.value === "Stopped") {
|
||||
swipeView.currentIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function stateValue(name) {
|
||||
var stateType = root.deviceClass.stateTypes.findByName(name);
|
||||
if (!stateType) return null
|
||||
@ -36,8 +42,36 @@ DevicePageBase {
|
||||
engine.deviceManager.executeAction(device.id, actionTypeId, params)
|
||||
}
|
||||
|
||||
function executeBrowserItem(itemId) {
|
||||
d.pendingItemId = itemId
|
||||
d.pendingBrowserItemId = engine.deviceManager.executeBrowserItem(device.id, itemId);
|
||||
}
|
||||
|
||||
readonly property State playbackState: device.states.getState(deviceClass.stateTypes.findByName("playbackStatus").id)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int pendingBrowserItemId: -1
|
||||
property string pendingItemId: ""
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.deviceManager
|
||||
onExecuteBrowserItemReply: {
|
||||
print("Execute reply:", params, params.id, params["id"], d.pendingBrowserItemId)
|
||||
if (params.id === d.pendingBrowserItemId) {
|
||||
d.pendingBrowserItemId = -1;
|
||||
d.pendingItemId = ""
|
||||
print("yep finished")
|
||||
if (params.params.deviceError === "DeviceErrorNoError") {
|
||||
swipeView.currentIndex = 0;
|
||||
} else {
|
||||
header.showInfo(qsTr("Error: %").arg(params.params.deviceError), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
id: swipeView
|
||||
anchors.fill: parent
|
||||
@ -133,7 +167,7 @@ DevicePageBase {
|
||||
onClicked: {
|
||||
print("clicked:", model.id)
|
||||
if (model.executable) {
|
||||
engine.deviceManager.executeBrowserItem(root.device.id, model.id)
|
||||
root.executeBrowserItem(model.id)
|
||||
} else if (model.browsable) {
|
||||
internalPageStack.push(internalBrowserPage, {device: root.device, nodeId: model.id})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user