Initial work on the device browser
This commit is contained in:
parent
ef2f213a6b
commit
9dfde053ca
@ -21,6 +21,8 @@
|
||||
#include "devicemanager.h"
|
||||
#include "engine.h"
|
||||
#include "jsonrpc/jsontypes.h"
|
||||
#include "types/browseritems.h"
|
||||
#include "types/browseritem.h"
|
||||
#include <QMetaEnum>
|
||||
|
||||
DeviceManager::DeviceManager(JsonRpcClient* jsonclient, QObject *parent) :
|
||||
@ -425,3 +427,62 @@ 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)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", deviceId.toString());
|
||||
params.insert("nodeId", nodeId);
|
||||
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();
|
||||
itemModel->setBusy(true);
|
||||
QPointer<BrowserItems> itemModelPtr(itemModel);
|
||||
m_browsingRequests.insert(id, itemModelPtr);
|
||||
|
||||
return itemModel;
|
||||
}
|
||||
|
||||
void DeviceManager::browseDeviceResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Browsing response:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
|
||||
int id = params.value("id").toInt();
|
||||
if (!m_browsingRequests.contains(id)) {
|
||||
qWarning() << "Received a browsing reply for an id we don't know.";
|
||||
return;
|
||||
}
|
||||
|
||||
QPointer<BrowserItems> itemModel = m_browsingRequests.take(id);
|
||||
if (!itemModel) {
|
||||
qDebug() << "BrowserItems model seems to have disappeared. Discarding browsing result.";
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const QVariant &itemVariant, params.value("params").toMap().value("items").toList()) {
|
||||
QVariantMap itemMap = itemVariant.toMap();
|
||||
BrowserItem *item = new BrowserItem(itemMap.value("id").toString(), this);
|
||||
item->setDisplayName(itemMap.value("displayName").toString());
|
||||
item->setDescription(itemMap.value("description").toString());
|
||||
item->setThumbnail(itemMap.value("thumbnail").toString());
|
||||
item->setExecutable(itemMap.value("executable").toBool());
|
||||
item->setBrowsable(itemMap.value("browsable").toBool());
|
||||
itemModel->addBrowserItem(item);
|
||||
}
|
||||
|
||||
itemModel->setBusy(false);
|
||||
}
|
||||
|
||||
void DeviceManager::executeBrowserItem(const QUuid &deviceId, const QString &nodeId)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", deviceId);
|
||||
params.insert("nodeId", nodeId);
|
||||
m_jsonClient->sendCommand("Devices.ExecuteBrowserItem", params, this, "executeBrowserItemResponse");
|
||||
}
|
||||
|
||||
void DeviceManager::executeBrowserItemResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Execute Browser Item finished" << params;
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "types/plugins.h"
|
||||
#include "jsonrpc/jsonhandler.h"
|
||||
#include "jsonrpc/jsonrpcclient.h"
|
||||
class BrowserItems;
|
||||
|
||||
class DeviceManager : public JsonHandler
|
||||
{
|
||||
@ -73,6 +74,8 @@ 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);
|
||||
|
||||
private:
|
||||
Q_INVOKABLE void notificationReceived(const QVariantMap &data);
|
||||
@ -89,6 +92,8 @@ private:
|
||||
Q_INVOKABLE void editDeviceResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void executeActionResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void reconfigureDeviceResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void browseDeviceResponse(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE void executeBrowserItemResponse(const QVariantMap ¶ms);
|
||||
|
||||
public slots:
|
||||
void savePluginConfig(const QUuid &pluginId);
|
||||
@ -117,6 +122,8 @@ private:
|
||||
|
||||
JsonRpcClient *m_jsonClient = nullptr;
|
||||
|
||||
QHash<int, QPointer<BrowserItems> > m_browsingRequests;
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEMANAGER_H
|
||||
|
||||
@ -75,6 +75,7 @@ DeviceClass *JsonTypes::unpackDeviceClass(const QVariantMap &deviceClassMap, QOb
|
||||
deviceClass->setDisplayName(deviceClassMap.value("displayName").toString());
|
||||
deviceClass->setId(deviceClassMap.value("id").toUuid());
|
||||
deviceClass->setVendorId(deviceClassMap.value("vendorId").toUuid());
|
||||
deviceClass->setBrowsable(deviceClassMap.value("browsable").toBool());
|
||||
QVariantList createMethodsList = deviceClassMap.value("createMethods").toList();
|
||||
QStringList createMethods;
|
||||
foreach (QVariant method, createMethodsList) {
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#include "types/statedescriptor.h"
|
||||
#include "types/stateevaluator.h"
|
||||
#include "types/stateevaluators.h"
|
||||
#include "types/browseritems.h"
|
||||
#include "types/browseritem.h"
|
||||
#include "models/logsmodel.h"
|
||||
#include "models/logsmodelng.h"
|
||||
#include "models/valuelogsproxymodel.h"
|
||||
@ -109,6 +111,9 @@ void registerQmlTypes() {
|
||||
qmlRegisterUncreatableType<State>(uri, 1, 0, "State", "Can't create this in QML. Get it from the States.");
|
||||
qmlRegisterUncreatableType<States>(uri, 1, 0, "States", "Can't create this in QML. Get it from the Device.");
|
||||
|
||||
qmlRegisterUncreatableType<BrowserItems>(uri, 1, 0, "BrowserItems", "Can't create this in QML. Get it from DeviceManager.");
|
||||
qmlRegisterUncreatableType<BrowserItem>(uri, 1, 0, "BrowserItem", "Can't create this in QML. Get it from BroweserItems.");
|
||||
|
||||
qmlRegisterUncreatableType<Vendor>(uri, 1, 0, "Vendor", "Can't create this in QML. Get it from the Vendors.");
|
||||
qmlRegisterUncreatableType<Vendors>(uri, 1, 0, "Vendors", "Can't create this in QML. Get it from the DeviceManager.");
|
||||
qmlRegisterType<VendorsProxy>(uri, 1, 0, "VendorsProxy");
|
||||
|
||||
@ -8,6 +8,8 @@ QT -= gui
|
||||
QT += network
|
||||
|
||||
HEADERS += \
|
||||
types/browseritem.h \
|
||||
types/browseritems.h \
|
||||
types/networkdevice.h \
|
||||
types/networkdevices.h \
|
||||
types/package.h \
|
||||
@ -62,6 +64,8 @@ HEADERS += \
|
||||
types/wirelessaccesspoints.h \
|
||||
|
||||
SOURCES += \
|
||||
types/browseritem.cpp \
|
||||
types/browseritems.cpp \
|
||||
types/networkdevice.cpp \
|
||||
types/networkdevices.cpp \
|
||||
types/package.cpp \
|
||||
|
||||
63
libnymea-common/types/browseritem.cpp
Normal file
63
libnymea-common/types/browseritem.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "browseritem.h"
|
||||
|
||||
BrowserItem::BrowserItem(const QString &id, QObject *parent):
|
||||
QObject(parent),
|
||||
m_id(id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString BrowserItem::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString BrowserItem::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
void BrowserItem::setDisplayName(const QString &displayName)
|
||||
{
|
||||
m_displayName = displayName;
|
||||
}
|
||||
|
||||
QString BrowserItem::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void BrowserItem::setDescription(const QString &description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
QString BrowserItem::thumbnail() const
|
||||
{
|
||||
return m_thumbnail;
|
||||
}
|
||||
|
||||
void BrowserItem::setThumbnail(const QString &thumbnail)
|
||||
{
|
||||
m_thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
bool BrowserItem::executable() const
|
||||
{
|
||||
return m_executable;
|
||||
}
|
||||
|
||||
void BrowserItem::setExecutable(bool executable)
|
||||
{
|
||||
m_executable = executable;
|
||||
}
|
||||
|
||||
bool BrowserItem::browsable() const
|
||||
{
|
||||
return m_browsable;
|
||||
}
|
||||
|
||||
void BrowserItem::setBrowsable(bool browsable)
|
||||
{
|
||||
m_browsable = browsable;
|
||||
}
|
||||
46
libnymea-common/types/browseritem.h
Normal file
46
libnymea-common/types/browseritem.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef BROWSERITEM_H
|
||||
#define BROWSERITEM_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
|
||||
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 thumbnail READ thumbnail CONSTANT)
|
||||
Q_PROPERTY(bool executable READ executable CONSTANT)
|
||||
Q_PROPERTY(bool browsable READ browsable CONSTANT)
|
||||
|
||||
public:
|
||||
explicit BrowserItem(const QString &id, QObject *parent = nullptr);
|
||||
|
||||
QString id() const;
|
||||
|
||||
QString displayName() const;
|
||||
void setDisplayName(const QString &displayName);
|
||||
|
||||
QString description() const;
|
||||
void setDescription(const QString &description);
|
||||
|
||||
QString thumbnail() const;
|
||||
void setThumbnail(const QString &thumbnail);
|
||||
|
||||
bool executable() const;
|
||||
void setExecutable(bool executable);
|
||||
|
||||
bool browsable() const;
|
||||
void setBrowsable(bool browsable);
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
QString m_description;
|
||||
QString m_thumbnail;
|
||||
bool m_executable = false;
|
||||
bool m_browsable = false;
|
||||
};
|
||||
|
||||
#endif // BROWSERITEM_H
|
||||
73
libnymea-common/types/browseritems.cpp
Normal file
73
libnymea-common/types/browseritems.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "browseritems.h"
|
||||
#include "browseritem.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
BrowserItems::BrowserItems(QObject *parent): QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BrowserItems::~BrowserItems()
|
||||
{
|
||||
qDebug() << "Deleting BrowserItems";
|
||||
}
|
||||
|
||||
bool BrowserItems::busy() const
|
||||
{
|
||||
return m_busy;
|
||||
}
|
||||
|
||||
int BrowserItems::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant BrowserItems::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case RoleId:
|
||||
return m_list.at(index.row())->id();
|
||||
case RoleDisplayName:
|
||||
return m_list.at(index.row())->displayName();
|
||||
case RoleDescription:
|
||||
return m_list.at(index.row())->description();
|
||||
case RoleThumbnail:
|
||||
return m_list.at(index.row())->thumbnail();
|
||||
case RoleExecutable:
|
||||
return m_list.at(index.row())->executable();
|
||||
case RoleBrowsable:
|
||||
return m_list.at(index.row())->browsable();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> BrowserItems::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleId, "id");
|
||||
roles.insert(RoleDisplayName, "displayName");
|
||||
roles.insert(RoleDescription, "description");
|
||||
roles.insert(RoleThumbnail, "thumbnail");
|
||||
roles.insert(RoleExecutable, "executable");
|
||||
roles.insert(RoleBrowsable, "browsable");
|
||||
return roles;
|
||||
}
|
||||
|
||||
void BrowserItems::addBrowserItem(BrowserItem *browserItem)
|
||||
{
|
||||
browserItem->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(browserItem);
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void BrowserItems::setBusy(bool busy)
|
||||
{
|
||||
if (m_busy != busy) {
|
||||
m_busy = busy;
|
||||
emit busyChanged();
|
||||
}
|
||||
}
|
||||
50
libnymea-common/types/browseritems.h
Normal file
50
libnymea-common/types/browseritems.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef BROWSERITEMS_H
|
||||
#define BROWSERITEMS_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class BrowserItem;
|
||||
|
||||
class BrowserItems: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
RoleId,
|
||||
RoleDisplayName,
|
||||
RoleDescription,
|
||||
RoleThumbnail,
|
||||
RoleBrowsable,
|
||||
RoleExecutable
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit BrowserItems(QObject *parent = nullptr);
|
||||
virtual ~BrowserItems() override;
|
||||
|
||||
bool busy() const;
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
virtual QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
virtual void addBrowserItem(BrowserItem *browserItem);
|
||||
void setBusy(bool busy);
|
||||
|
||||
// Q_INVOKABLE virtual BrowserItem* get(int index) const;
|
||||
// Q_INVOKABLE virtual BrowserItem* getBrowserItem(const QString &itemId);
|
||||
|
||||
// void clear();
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void busyChanged();
|
||||
|
||||
protected:
|
||||
bool m_busy = false;
|
||||
QList<BrowserItem*> m_list;
|
||||
};
|
||||
|
||||
#endif // BROWSERITEMS_H
|
||||
@ -167,6 +167,16 @@ QString DeviceClass::baseInterface() const
|
||||
|
||||
}
|
||||
|
||||
bool DeviceClass::browsable() const
|
||||
{
|
||||
return m_browsable;
|
||||
}
|
||||
|
||||
void DeviceClass::setBrowsable(bool browsable)
|
||||
{
|
||||
m_browsable = browsable;
|
||||
}
|
||||
|
||||
ParamTypes *DeviceClass::paramTypes() const
|
||||
{
|
||||
return m_paramTypes;
|
||||
|
||||
@ -46,6 +46,7 @@ class DeviceClass : public QObject
|
||||
Q_PROPERTY(SetupMethod setupMethod READ setupMethod CONSTANT)
|
||||
Q_PROPERTY(QStringList interfaces READ interfaces CONSTANT)
|
||||
Q_PROPERTY(QString baseInterface READ baseInterface CONSTANT)
|
||||
Q_PROPERTY(bool browsable READ browsable CONSTANT)
|
||||
Q_PROPERTY(ParamTypes *paramTypes READ paramTypes NOTIFY paramTypesChanged)
|
||||
Q_PROPERTY(ParamTypes *settingsTypes READ settingsTypes NOTIFY settingsTypesChanged)
|
||||
Q_PROPERTY(ParamTypes *discoveryParamTypes READ discoveryParamTypes NOTIFY discoveryParamTypesChanged)
|
||||
@ -91,6 +92,9 @@ public:
|
||||
|
||||
QString baseInterface() const;
|
||||
|
||||
bool browsable() const;
|
||||
void setBrowsable(bool browsable);
|
||||
|
||||
ParamTypes *paramTypes() const;
|
||||
void setParamTypes(ParamTypes *paramTypes);
|
||||
|
||||
@ -120,6 +124,7 @@ private:
|
||||
QStringList m_createMethods;
|
||||
SetupMethod m_setupMethod;
|
||||
QStringList m_interfaces;
|
||||
bool m_browsable = false;
|
||||
|
||||
ParamTypes *m_paramTypes = nullptr;
|
||||
ParamTypes *m_settingsTypes = nullptr;
|
||||
|
||||
@ -181,5 +181,6 @@
|
||||
<file>ui/images/lock-closed.svg</file>
|
||||
<file>ui/images/lock-open.svg</file>
|
||||
<file>ui/images/system-update.svg</file>
|
||||
<file>ui/images/folder-symbolic.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -184,5 +184,6 @@
|
||||
<file>ui/components/UpdateRunningOverlay.qml</file>
|
||||
<file>ui/connection/SetupWizard.qml</file>
|
||||
<file>ui/system/NetworkSettingsPage.qml</file>
|
||||
<file>ui/devicepages/DeviceBrowserPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
55
nymea-app/ui/devicepages/DeviceBrowserPage.qml
Normal file
55
nymea-app/ui/devicepages/DeviceBrowserPage.qml
Normal file
@ -0,0 +1,55 @@
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
header: GuhHeader {
|
||||
text: qsTr("Browse %1").arg(root.device.name)
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
property Device device: null
|
||||
property string nodeId: ""
|
||||
|
||||
Component.onCompleted: {
|
||||
d.model = engine.deviceManager.browseDevice(root.device.id, root.nodeId);
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property BrowserItems model: null
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
anchors.fill: parent
|
||||
model: d.model
|
||||
|
||||
delegate: MeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: model.displayName
|
||||
progressive: model.browsable
|
||||
subText: model.description
|
||||
prominentSubText: false
|
||||
iconName: model.thumbnail
|
||||
|
||||
onClicked: {
|
||||
print("clicked:", model.id)
|
||||
if (model.executable) {
|
||||
engine.deviceManager.executeBrowserItem(root.device.id, model.id)
|
||||
} else if (model.browsable) {
|
||||
pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device, nodeId: model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: listView.model.busy
|
||||
visible: running
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,6 +18,14 @@ Page {
|
||||
text: device.name
|
||||
onBackPressed: pageStack.pop()
|
||||
|
||||
HeaderButton {
|
||||
imageSource: "../images/folder-symbolic.svg"
|
||||
visible: root.deviceClass.browsable
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device})
|
||||
}
|
||||
}
|
||||
|
||||
HeaderButton {
|
||||
imageSource: "../images/navigation-menu.svg"
|
||||
onClicked: thingMenu.open();
|
||||
|
||||
17
nymea-app/ui/images/folder-symbolic.svg
Normal file
17
nymea-app/ui/images/folder-symbolic.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg id="svg4874" width="96" height="96" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata id="metadata4879">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g id="layer1" transform="translate(67.857 -78.505)">
|
||||
<rect id="rect4782" transform="rotate(90)" x="78.505" y="-28.143" width="96" height="96" style="color:#000000;fill:none"/>
|
||||
<path id="path4643" d="m-47.869 86.504-0.01172 2e-3c-5.0328 0.05818-8.7136-0.12027-11.725 1.541-1.5055 0.83064-2.6968 2.2356-3.3555 3.9902-0.65866 1.7547-0.89648 3.8364-0.89648 6.4668v54.002c0 2.6304 0.23782 4.7121 0.89648 6.4668 0.65866 1.7546 1.85 3.1596 3.3555 3.9902 3.011 1.6613 6.6918 1.4848 11.725 1.543h0.01172 56.023 0.011719c5.0328-0.0582 8.7136 0.11832 11.725-1.543 1.5055-0.83064 2.6968-2.2356 3.3555-3.9902 0.65866-1.7547 0.89648-3.8364 0.89648-6.4668v-38c0-2.6333-0.24451-4.7263-0.91016-6.4883-0.66565-1.762-1.8593-3.1729-3.3691-4.0117-3.0197-1.6776-6.7207-1.5-11.721-1.5h-46c-5 0-8.701-0.17761-11.721 1.5-1.5098 0.8388-2.7035 2.2497-3.3691 4.0117-0.66565 1.762-0.91016 3.855-0.91016 6.4883v40h4v-40c0-2.3667 0.25549-4.0257 0.65234-5.0762 0.39685-1.0505 0.82821-1.5146 1.5684-1.9258 1.4803-0.82239 4.7793-0.99805 9.7793-0.99805h46c5 0 8.299 0.17566 9.7793 0.99805 0.74015 0.41119 1.1715 0.87528 1.5684 1.9258 0.39685 1.0505 0.65234 2.7095 0.65234 5.0762v38c0 2.3696-0.25037 4.0209-0.64062 5.0606-0.39025 1.0396-0.80933 1.4898-1.543 1.8945-1.4645 0.80804-4.7782 0.98616-9.8164 1.0449h-55.977-0.02344c-5.0383-0.0588-8.3519-0.23688-9.8164-1.0449-0.73364-0.40478-1.1508-0.85491-1.541-1.8945-0.39025-1.0396-0.64258-2.691-0.64258-5.0606v-54.002c0-2.3696 0.25232-4.0209 0.64258-5.0605 0.39025-1.0396 0.80738-1.4898 1.541-1.8945 1.4645-0.80804 4.7782-0.98616 9.8164-1.0449l20.172 2e-3 6 6 33.828-2e-3v-4l-32.172 2e-3 -6-6z" style="color-rendering:auto;color:#000000;dominant-baseline:auto;fill:#808080;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
Reference in New Issue
Block a user