Remote-canvas image support, partially working.
This commit is contained in:
parent
57432c20ad
commit
6c0e9b747d
10 changed files with 246 additions and 30 deletions
|
@ -32,6 +32,8 @@ set(SOURCES
|
||||||
canvastreemodel.h
|
canvastreemodel.h
|
||||||
fgqcanvasfontcache.cpp
|
fgqcanvasfontcache.cpp
|
||||||
fgqcanvasfontcache.h
|
fgqcanvasfontcache.h
|
||||||
|
fgqcanvasimageloader.cpp
|
||||||
|
fgqcanvasimageloader.h
|
||||||
)
|
)
|
||||||
|
|
||||||
qt5_wrap_ui(uic_sources temporarywidget.ui)
|
qt5_wrap_ui(uic_sources temporarywidget.ui)
|
||||||
|
|
|
@ -52,6 +52,12 @@ FGQCanvasFontCache *FGQCanvasFontCache::instance()
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGQCanvasFontCache::setHost(QString hostName, int portNumber)
|
||||||
|
{
|
||||||
|
m_hostName = hostName;
|
||||||
|
m_port = portNumber;
|
||||||
|
}
|
||||||
|
|
||||||
void FGQCanvasFontCache::onFontDownloadFinished()
|
void FGQCanvasFontCache::onFontDownloadFinished()
|
||||||
{
|
{
|
||||||
QByteArray fontPath = sender()->property("font").toByteArray();
|
QByteArray fontPath = sender()->property("font").toByteArray();
|
||||||
|
@ -90,7 +96,11 @@ void FGQCanvasFontCache::lookupFile(QByteArray name)
|
||||||
{
|
{
|
||||||
QString path = QStandardPaths::locate(QStandardPaths::CacheLocation, name);
|
QString path = QStandardPaths::locate(QStandardPaths::CacheLocation, name);
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
QUrl url = QUrl("http://localhost:8080/Fonts/" + name);
|
QUrl url;
|
||||||
|
url.setScheme("http");
|
||||||
|
url.setHost(m_hostName);
|
||||||
|
url.setPort(m_port);
|
||||||
|
url.setPath("/Fonts/" + name);
|
||||||
|
|
||||||
Q_FOREACH (QNetworkReply* transfer, m_transfers) {
|
Q_FOREACH (QNetworkReply* transfer, m_transfers) {
|
||||||
if (transfer->url() == url) {
|
if (transfer->url() == url) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ public:
|
||||||
static void initialise(QNetworkAccessManager* nam);
|
static void initialise(QNetworkAccessManager* nam);
|
||||||
static FGQCanvasFontCache* instance();
|
static FGQCanvasFontCache* instance();
|
||||||
|
|
||||||
|
void setHost(QString hostName, int portNumber);
|
||||||
signals:
|
signals:
|
||||||
void fontLoaded(QByteArray name);
|
void fontLoaded(QByteArray name);
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ private slots:
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager* m_downloader;
|
QNetworkAccessManager* m_downloader;
|
||||||
QHash<QByteArray, QFont> m_cache;
|
QHash<QByteArray, QFont> m_cache;
|
||||||
|
QString m_hostName;
|
||||||
|
int m_port;
|
||||||
|
|
||||||
void lookupFile(QByteArray name);
|
void lookupFile(QByteArray name);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "fgcanvaspaintcontext.h"
|
#include "fgcanvaspaintcontext.h"
|
||||||
#include "localprop.h"
|
#include "localprop.h"
|
||||||
|
#include "fgqcanvasimageloader.h"
|
||||||
|
|
||||||
FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) :
|
FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) :
|
||||||
FGCanvasElement(pr, prop)
|
FGCanvasElement(pr, prop)
|
||||||
|
@ -45,10 +46,31 @@ void FGQCanvasImage::markImageDirty()
|
||||||
|
|
||||||
void FGQCanvasImage::rebuildImage() const
|
void FGQCanvasImage::rebuildImage() const
|
||||||
{
|
{
|
||||||
qDebug() << "source" << _propertyRoot->value("source", QString());
|
|
||||||
qDebug() << "src" << _propertyRoot->value("src", QString());
|
|
||||||
qDebug() << "file" << _propertyRoot->value("file", QString());
|
|
||||||
|
|
||||||
|
QByteArray file = _propertyRoot->value("file", QByteArray()).toByteArray();
|
||||||
|
if (!file.isEmpty()) {
|
||||||
|
_image = FGQCanvasImageLoader::instance()->getImage(file);
|
||||||
|
|
||||||
|
|
||||||
|
if (_image.isNull()) {
|
||||||
|
// get notified when the image loads
|
||||||
|
FGQCanvasImageLoader::instance()->connectToImageLoaded(file,
|
||||||
|
const_cast<FGQCanvasImage*>(this),
|
||||||
|
SLOT(markImageDirty()));
|
||||||
|
} else {
|
||||||
|
qDebug() << "have image" << _image.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qDebug() << "source" << _propertyRoot->value("source", QString());
|
||||||
|
qDebug() << "src" << _propertyRoot->value("src", QString());
|
||||||
|
}
|
||||||
|
|
||||||
|
_destSize = QSizeF(_propertyRoot->value("size[0]", 0.0).toFloat(),
|
||||||
|
_propertyRoot->value("size[1]", 0.0).toFloat());
|
||||||
|
qDebug() << "dest-size" << _destSize;
|
||||||
|
|
||||||
|
_imageDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGQCanvasImage::markStyleDirty()
|
void FGQCanvasImage::markStyleDirty()
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
class FGQCanvasImage : public FGCanvasElement
|
class FGQCanvasImage : public FGCanvasElement
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop);
|
FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop);
|
||||||
|
|
||||||
|
@ -15,12 +16,15 @@ protected:
|
||||||
|
|
||||||
virtual void markStyleDirty() override;
|
virtual void markStyleDirty() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void markImageDirty();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool onChildAdded(LocalProp *prop) override;
|
bool onChildAdded(LocalProp *prop) override;
|
||||||
|
|
||||||
void rebuildImage() const;
|
void rebuildImage() const;
|
||||||
|
|
||||||
void markImageDirty();
|
|
||||||
private:
|
private:
|
||||||
mutable bool _imageDirty;
|
mutable bool _imageDirty;
|
||||||
mutable QPixmap _image;
|
mutable QPixmap _image;
|
||||||
|
|
108
utils/fgqcanvas/fgqcanvasimageloader.cpp
Normal file
108
utils/fgqcanvas/fgqcanvasimageloader.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#include "fgqcanvasimageloader.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
|
static FGQCanvasImageLoader* static_instance = nullptr;
|
||||||
|
|
||||||
|
class TransferSignalHolder : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TransferSignalHolder(QObject* pr) : QObject(pr) { }
|
||||||
|
signals:
|
||||||
|
void trigger();
|
||||||
|
};
|
||||||
|
|
||||||
|
FGQCanvasImageLoader::FGQCanvasImageLoader(QNetworkAccessManager* dl)
|
||||||
|
: m_downloader(dl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGQCanvasImageLoader::onDownloadFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
|
QPixmap pm;
|
||||||
|
if (!pm.loadFromData(reply->readAll())) {
|
||||||
|
qWarning() << "image loading failed";
|
||||||
|
} else {
|
||||||
|
qDebug() << "did download:" << reply->property("image").toByteArray();
|
||||||
|
m_cache.insert(reply->property("image").toByteArray(), pm);
|
||||||
|
|
||||||
|
TransferSignalHolder* signalHolder = reply->findChild<TransferSignalHolder*>("holder");
|
||||||
|
if (signalHolder) {
|
||||||
|
qDebug() << "triggering image updates";
|
||||||
|
signalHolder->trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_transfers.removeOne(reply);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
FGQCanvasImageLoader *FGQCanvasImageLoader::instance()
|
||||||
|
{
|
||||||
|
return static_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGQCanvasImageLoader::initialise(QNetworkAccessManager *dl)
|
||||||
|
{
|
||||||
|
Q_ASSERT(static_instance == nullptr);
|
||||||
|
static_instance = new FGQCanvasImageLoader(dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGQCanvasImageLoader::setHost(QString hostName, int portNumber)
|
||||||
|
{
|
||||||
|
m_hostName = hostName;
|
||||||
|
m_port = portNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap FGQCanvasImageLoader::getImage(const QByteArray &imagePath)
|
||||||
|
{
|
||||||
|
if (m_cache.contains(imagePath)) {
|
||||||
|
// cached, easy
|
||||||
|
return m_cache.value(imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url;
|
||||||
|
url.setScheme("http");
|
||||||
|
url.setHost(m_hostName);
|
||||||
|
url.setPort(m_port);
|
||||||
|
url.setPath("/aircraft-dir/" + imagePath);
|
||||||
|
|
||||||
|
Q_FOREACH (QNetworkReply* transfer, m_transfers) {
|
||||||
|
if (transfer->url() == url) {
|
||||||
|
return QPixmap(); // transfer already active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "requesting image" << url;
|
||||||
|
QNetworkReply* reply = m_downloader->get(QNetworkRequest(url));
|
||||||
|
reply->setProperty("image", imagePath);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &FGQCanvasImageLoader::onDownloadFinished);
|
||||||
|
m_transfers.append(reply);
|
||||||
|
|
||||||
|
return QPixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGQCanvasImageLoader::connectToImageLoaded(const QByteArray &imagePath, QObject *receiver, const char *slot)
|
||||||
|
{
|
||||||
|
Q_FOREACH (QNetworkReply* transfer, m_transfers) {
|
||||||
|
if (transfer->property("image").toByteArray() == imagePath) {
|
||||||
|
QObject* signalHolder = transfer->findChild<QObject*>("holder");
|
||||||
|
if (!signalHolder) {
|
||||||
|
signalHolder = new TransferSignalHolder(transfer);
|
||||||
|
signalHolder->setObjectName("holder");
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(signalHolder, SIGNAL(trigger()), receiver, slot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "no transfer active for" << imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "fgqcanvasimageloader.moc"
|
49
utils/fgqcanvas/fgqcanvasimageloader.h
Normal file
49
utils/fgqcanvas/fgqcanvasimageloader.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef FGQCANVASIMAGELOADER_H
|
||||||
|
#define FGQCANVASIMAGELOADER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
|
class FGQCanvasImageLoader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static FGQCanvasImageLoader* instance();
|
||||||
|
|
||||||
|
static void initialise(QNetworkAccessManager* dl);
|
||||||
|
|
||||||
|
void setHost(QString hostName, int portNumber);
|
||||||
|
|
||||||
|
QPixmap getImage(const QByteArray& imagePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief connectToImageLoaded - allow images to discover when they are loaded
|
||||||
|
* @param imagePath - FGFS host relative path as found in the canvas (will be resolved
|
||||||
|
* against aircraft-data, and potentially other places)
|
||||||
|
* @param receiver - normal connect() receiver object
|
||||||
|
* @param slot - slot macro
|
||||||
|
*/
|
||||||
|
void connectToImageLoaded(const QByteArray& imagePath, QObject* receiver, const char* slot);
|
||||||
|
signals:
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit FGQCanvasImageLoader(QNetworkAccessManager* dl);
|
||||||
|
|
||||||
|
void onDownloadFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager* m_downloader;
|
||||||
|
QString m_hostName;
|
||||||
|
int m_port;
|
||||||
|
|
||||||
|
QMap<QByteArray, QPixmap> m_cache;
|
||||||
|
QList<QNetworkReply*> m_transfers;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FGQCANVASIMAGELOADER_H
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkDiskCache>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "fgqcanvasfontcache.h"
|
#include "fgqcanvasfontcache.h"
|
||||||
|
#include "fgqcanvasimageloader.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -15,10 +18,18 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QNetworkAccessManager* downloader = new QNetworkAccessManager;
|
QNetworkAccessManager* downloader = new QNetworkAccessManager;
|
||||||
|
|
||||||
|
QNetworkDiskCache* cache = new QNetworkDiskCache;
|
||||||
|
cache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||||
|
downloader->setCache(cache); // takes ownership
|
||||||
|
|
||||||
FGQCanvasFontCache::initialise(downloader);
|
FGQCanvasFontCache::initialise(downloader);
|
||||||
|
FGQCanvasImageLoader::initialise(downloader);
|
||||||
|
|
||||||
TemporaryWidget w;
|
TemporaryWidget w;
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
return a.exec();
|
int result = a.exec();
|
||||||
|
delete downloader;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
// ws://localhost:8080/PropertyTreeMirror/canvas/by-index/texture[3]
|
#include "fgqcanvasfontcache.h"
|
||||||
|
#include "fgqcanvasimageloader.h"
|
||||||
#include "canvastreemodel.h"
|
#include "canvastreemodel.h"
|
||||||
#include "localprop.h"
|
#include "localprop.h"
|
||||||
|
|
||||||
|
@ -24,24 +24,21 @@ TemporaryWidget::TemporaryWidget(QWidget *parent) :
|
||||||
|
|
||||||
TemporaryWidget::~TemporaryWidget()
|
TemporaryWidget::~TemporaryWidget()
|
||||||
{
|
{
|
||||||
|
disconnect(&m_webSocket, &QWebSocket::disconnected, this, &TemporaryWidget::onSocketClosed);
|
||||||
|
m_webSocket.close();
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryWidget::onStartConnect()
|
void TemporaryWidget::onStartConnect()
|
||||||
{
|
{
|
||||||
QString wsUrl = ui->socketURL->text();
|
QUrl wsUrl;
|
||||||
if (!wsUrl.startsWith("ws")) {
|
wsUrl.setScheme("ws");
|
||||||
qWarning() << "Not a web-socket URL" << wsUrl;
|
wsUrl.setHost(ui->hostName->text());
|
||||||
return;
|
wsUrl.setPort(ui->portEdit->text().toInt());
|
||||||
}
|
|
||||||
|
|
||||||
// string clean up, to ensure our root path has a leading slash but
|
// string clean up, to ensure our root path has a leading slash but
|
||||||
// no trailing slash
|
// no trailing slash
|
||||||
QString propPath = ui->propertyPath->text();
|
QString propPath = ui->propertyPath->text();
|
||||||
if (wsUrl.endsWith('/')) {
|
|
||||||
wsUrl.truncate(wsUrl.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString rootPath = propPath;
|
QString rootPath = propPath;
|
||||||
if (!propPath.startsWith('/')) {
|
if (!propPath.startsWith('/')) {
|
||||||
rootPath = '/' + propPath;
|
rootPath = '/' + propPath;
|
||||||
|
@ -51,7 +48,7 @@ void TemporaryWidget::onStartConnect()
|
||||||
rootPath.chop(1);
|
rootPath.chop(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url = QUrl(wsUrl + rootPath);
|
wsUrl.setPath("/PropertyTreeMirror" + rootPath);
|
||||||
rootPropertyPath = rootPath.toUtf8();
|
rootPropertyPath = rootPath.toUtf8();
|
||||||
|
|
||||||
connect(&m_webSocket, &QWebSocket::connected, this, &TemporaryWidget::onConnected);
|
connect(&m_webSocket, &QWebSocket::connected, this, &TemporaryWidget::onConnected);
|
||||||
|
@ -59,9 +56,8 @@ void TemporaryWidget::onStartConnect()
|
||||||
|
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
|
||||||
qDebug() << "starting connection to:" << url;
|
qDebug() << "starting connection to:" << wsUrl;
|
||||||
m_webSocket.open(url);
|
m_webSocket.open(wsUrl);
|
||||||
m_webSocket.sendTextMessage("nothing"); // forces Mongoose to respond quicker
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryWidget::onConnected()
|
void TemporaryWidget::onConnected()
|
||||||
|
@ -78,6 +74,12 @@ void TemporaryWidget::onConnected()
|
||||||
|
|
||||||
m_canvasModel = new CanvasTreeModel(ui->canvas->rootElement());
|
m_canvasModel = new CanvasTreeModel(ui->canvas->rootElement());
|
||||||
ui->treeView->setModel(m_canvasModel);
|
ui->treeView->setModel(m_canvasModel);
|
||||||
|
|
||||||
|
FGQCanvasFontCache::instance()->setHost(ui->hostName->text(),
|
||||||
|
ui->portEdit->text().toInt());
|
||||||
|
FGQCanvasImageLoader::instance()->setHost(ui->hostName->text(),
|
||||||
|
ui->portEdit->text().toInt());
|
||||||
|
m_webSocket.sendTextMessage("nonsense");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryWidget::onTextMessageReceived(QString message)
|
void TemporaryWidget::onTextMessageReceived(QString message)
|
||||||
|
@ -158,14 +160,16 @@ void TemporaryWidget::onSocketClosed()
|
||||||
void TemporaryWidget::saveSettings()
|
void TemporaryWidget::saveSettings()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.setValue("ws-host", ui->socketURL->text());
|
settings.setValue("ws-host", ui->hostName->text());
|
||||||
|
settings.setValue("ws-port", ui->portEdit->text());
|
||||||
settings.setValue("prop-path", ui->propertyPath->text());
|
settings.setValue("prop-path", ui->propertyPath->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryWidget::restoreSettings()
|
void TemporaryWidget::restoreSettings()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
ui->socketURL->setText(settings.value("ws-host").toString());
|
ui->hostName->setText(settings.value("ws-host").toString());
|
||||||
|
ui->portEdit->setText(settings.value("ws-port").toString());
|
||||||
ui->propertyPath->setText(settings.value("prop-path").toString());
|
ui->propertyPath->setText(settings.value("prop-path").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Connect</string>
|
<string>Connect</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout" columnstretch="1,0">
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -34,15 +34,12 @@
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enter a web-socket URL: (eg 'ws://localhost:8080/PropertyTreeMirror/')</string>
|
<string>Enter FlightGear host-name and port</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QTreeView" name="treeView"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="socketURL"/>
|
<widget class="QLineEdit" name="hostName"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QPushButton" name="connectButton">
|
<widget class="QPushButton" name="connectButton">
|
||||||
|
@ -51,9 +48,15 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="portEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QLineEdit" name="propertyPath"/>
|
<widget class="QLineEdit" name="propertyPath"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<widget class="QTreeView" name="treeView"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="stackPage2">
|
<widget class="QWidget" name="stackPage2">
|
||||||
|
|
Loading…
Add table
Reference in a new issue