From 15cdd7c91c33b3e472884ceb94ff54b3c47be599 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 21 Feb 2018 13:16:05 +0100 Subject: [PATCH] rework discovery --- guh-control/discovery/guhdiscovery.cpp | 39 ++++ guh-control/discovery/guhdiscovery.h | 35 +++ guh-control/discovery/upnpdiscovery.cpp | 23 +- guh-control/discovery/upnpdiscovery.h | 10 +- guh-control/discovery/zeroconfdiscovery.cpp | 10 +- guh-control/discovery/zeroconfdiscovery.h | 12 +- guh-control/guh-control.pro | 6 +- guh-control/main.cpp | 8 +- guh-control/ui/ConnectPage.qml | 231 +++++++------------- guh-control/ui/SettingsPage.qml | 30 ++- guh-control/ui/main.qml | 14 +- 11 files changed, 198 insertions(+), 220 deletions(-) create mode 100644 guh-control/discovery/guhdiscovery.cpp create mode 100644 guh-control/discovery/guhdiscovery.h diff --git a/guh-control/discovery/guhdiscovery.cpp b/guh-control/discovery/guhdiscovery.cpp new file mode 100644 index 00000000..466f146c --- /dev/null +++ b/guh-control/discovery/guhdiscovery.cpp @@ -0,0 +1,39 @@ +#include "guhdiscovery.h" + +#include "upnpdiscovery.h" +#include "zeroconfdiscovery.h" + +GuhDiscovery::GuhDiscovery(QObject *parent) : QObject(parent) +{ + m_discoveryModel = new DiscoveryModel(this); + + m_upnp = new UpnpDiscovery(m_discoveryModel, this); + m_zeroConf = new ZeroconfDiscovery(m_discoveryModel, this); +} + +bool GuhDiscovery::discovering() const +{ + return m_discovering; +} + +void GuhDiscovery::setDiscovering(bool discovering) +{ + if (m_discovering != discovering) { + m_discovering = discovering; + // For zeroconf we'll ignore it as zeroconf doesn't do active discovery but just listens for changes in the net all the time + // If we don't have zeroconf available, start an active upnp discovery + if (!m_zeroConf->available()) { + if (discovering) { + m_upnp->discover(); + } else { + m_upnp->stopDiscovery(); + } + } + emit discoveringChanged(); + } +} + +DiscoveryModel *GuhDiscovery::discoveryModel() const +{ + return m_discoveryModel; +} diff --git a/guh-control/discovery/guhdiscovery.h b/guh-control/discovery/guhdiscovery.h new file mode 100644 index 00000000..f32a057f --- /dev/null +++ b/guh-control/discovery/guhdiscovery.h @@ -0,0 +1,35 @@ +#ifndef GUHDISCOVERY_H +#define GUHDISCOVERY_H + +#include + +class DiscoveryModel; +class UpnpDiscovery; +class ZeroconfDiscovery; + +class GuhDiscovery : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool discovering READ discovering WRITE setDiscovering NOTIFY discoveringChanged) + Q_PROPERTY(DiscoveryModel *discoveryModel READ discoveryModel CONSTANT) + +public: + explicit GuhDiscovery(QObject *parent = nullptr); + + bool discovering() const; + void setDiscovering(bool discovering); + + DiscoveryModel *discoveryModel() const; + +signals: + void discoveringChanged(); + +private: + bool m_discovering = false; + DiscoveryModel *m_discoveryModel = nullptr; + + UpnpDiscovery *m_upnp = nullptr; + ZeroconfDiscovery *m_zeroConf = nullptr; +}; + +#endif // GUHDISCOVERY_H diff --git a/guh-control/discovery/upnpdiscovery.cpp b/guh-control/discovery/upnpdiscovery.cpp index c18d0873..b7316963 100644 --- a/guh-control/discovery/upnpdiscovery.cpp +++ b/guh-control/discovery/upnpdiscovery.cpp @@ -24,19 +24,15 @@ #include #include -UpnpDiscovery::UpnpDiscovery(QObject *parent) : +UpnpDiscovery::UpnpDiscovery(DiscoveryModel *discoveryModel, QObject *parent) : QUdpSocket(parent), + m_discoveryModel(discoveryModel), m_discovering(false), m_available(false) { m_networkAccessManager = new QNetworkAccessManager(this); connect(m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpnpDiscovery::networkReplyFinished); - m_discoveryModel = new DiscoveryModel(this); - - m_timer.setSingleShot(true); - m_timer.setInterval(5000); - connect(&m_timer, &QTimer::timeout, this, &UpnpDiscovery::onTimeout); m_repeatTimer.setInterval(500); connect(&m_repeatTimer, &QTimer::timeout, this, &UpnpDiscovery::writeDiscoveryPacket); @@ -69,11 +65,6 @@ bool UpnpDiscovery::discovering() const return m_discovering; } -DiscoveryModel *UpnpDiscovery::discoveryModel() -{ - return m_discoveryModel; -} - bool UpnpDiscovery::available() const { return m_available; @@ -87,7 +78,6 @@ void UpnpDiscovery::discover() } qDebug() << "start discovering..."; - m_timer.start(); m_repeatTimer.start(); // m_discoveryModel->clearModel(); m_foundDevices.clear(); @@ -100,9 +90,7 @@ void UpnpDiscovery::discover() void UpnpDiscovery::stopDiscovery() { qDebug() << "stop discovering"; - m_timer.stop(); m_repeatTimer.stop(); - m_discoveryModel->clearModel(); setDiscovering(false); } @@ -268,10 +256,3 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply) reply->deleteLater(); } - -void UpnpDiscovery::onTimeout() -{ - qDebug() << "discovery timeout"; - m_repeatTimer.stop(); - setDiscovering(false); -} diff --git a/guh-control/discovery/upnpdiscovery.h b/guh-control/discovery/upnpdiscovery.h index c68c75c6..8e25c27e 100644 --- a/guh-control/discovery/upnpdiscovery.h +++ b/guh-control/discovery/upnpdiscovery.h @@ -33,15 +33,10 @@ class UpnpDiscovery : public QUdpSocket { Q_OBJECT - Q_PROPERTY(bool discovering READ discovering NOTIFY discoveringChanged) - Q_PROPERTY(bool available READ available NOTIFY availableChanged) - Q_PROPERTY(DiscoveryModel *discoveryModel READ discoveryModel NOTIFY discoveryModelChanged) - public: - explicit UpnpDiscovery(QObject *parent = 0); + explicit UpnpDiscovery(DiscoveryModel *discoveryModel, QObject *parent = 0); bool discovering() const; - DiscoveryModel *discoveryModel(); bool available() const; @@ -51,7 +46,6 @@ public: private: QNetworkAccessManager *m_networkAccessManager; - QTimer m_timer; QTimer m_repeatTimer; QHostAddress m_host; @@ -77,8 +71,6 @@ private slots: void error(QAbstractSocket::SocketError error); void readData(); void networkReplyFinished(QNetworkReply *reply); - void onTimeout(); - }; #endif // UPNPDISCOVERY_H diff --git a/guh-control/discovery/zeroconfdiscovery.cpp b/guh-control/discovery/zeroconfdiscovery.cpp index 7a637fa6..8be89e00 100644 --- a/guh-control/discovery/zeroconfdiscovery.cpp +++ b/guh-control/discovery/zeroconfdiscovery.cpp @@ -3,10 +3,10 @@ #include -ZeroconfDiscovery::ZeroconfDiscovery(QObject *parent) : QObject(parent) +ZeroconfDiscovery::ZeroconfDiscovery(DiscoveryModel *discoveryModel, QObject *parent) : + QObject(parent), + m_discoveryModel(discoveryModel) { - m_discoveryModel = new DiscoveryModel(this); - #ifdef WITH_AVAHI m_serviceBrowser = new QtAvahiServiceBrowser(this); connect(m_serviceBrowser, &QtAvahiServiceBrowser::serviceEntryAdded, this, &ZeroconfDiscovery::serviceEntryAdded); @@ -28,10 +28,6 @@ bool ZeroconfDiscovery::discovering() const return true; } -DiscoveryModel *ZeroconfDiscovery::discoveryModel() const -{ - return m_discoveryModel; -} #ifdef WITH_AVAHI void ZeroconfDiscovery::serviceEntryAdded(const AvahiServiceEntry &entry) { diff --git a/guh-control/discovery/zeroconfdiscovery.h b/guh-control/discovery/zeroconfdiscovery.h index bf63f78e..7d79a3e5 100644 --- a/guh-control/discovery/zeroconfdiscovery.h +++ b/guh-control/discovery/zeroconfdiscovery.h @@ -12,23 +12,13 @@ class ZeroconfDiscovery : public QObject { Q_OBJECT - Q_PROPERTY(bool discovering READ discovering NOTIFY discoveringChanged) - Q_PROPERTY(bool available READ available CONSTANT) - Q_PROPERTY(DiscoveryModel* discoveryModel READ discoveryModel CONSTANT) public: - explicit ZeroconfDiscovery(QObject *parent = nullptr); + explicit ZeroconfDiscovery(DiscoveryModel *discoveryModel, QObject *parent = nullptr); bool available() const; bool discovering() const; - DiscoveryModel* discoveryModel() const; - -signals: - void discoveringChanged(); - -public slots: - private: DiscoveryModel *m_discoveryModel; diff --git a/guh-control/guh-control.pro b/guh-control/guh-control.pro index 82ff64ff..d5fed17c 100644 --- a/guh-control/guh-control.pro +++ b/guh-control/guh-control.pro @@ -34,7 +34,8 @@ HEADERS += engine.h \ rulemanager.h \ models/rulesfiltermodel.h \ models/logsmodel.h \ - models/valuelogsproxymodel.h + models/valuelogsproxymodel.h \ + discovery/guhdiscovery.h SOURCES += main.cpp \ @@ -64,7 +65,8 @@ SOURCES += main.cpp \ rulemanager.cpp \ models/rulesfiltermodel.cpp \ models/logsmodel.cpp \ - models/valuelogsproxymodel.cpp + models/valuelogsproxymodel.cpp \ + discovery/guhdiscovery.cpp withavahi { DEFINES += WITH_AVAHI diff --git a/guh-control/main.cpp b/guh-control/main.cpp index 1940d2b5..fa740a6c 100644 --- a/guh-control/main.cpp +++ b/guh-control/main.cpp @@ -30,8 +30,8 @@ #include "devicesproxy.h" #include "pluginsproxy.h" #include "devicediscovery.h" -#include "discovery/upnpdiscovery.h" -#include "discovery/zeroconfdiscovery.h" +#include "discovery/guhdiscovery.h" +#include "discovery/discoverymodel.h" #include "interfacesmodel.h" #include "rulemanager.h" #include "models/rulesfiltermodel.h" @@ -112,8 +112,8 @@ int main(int argc, char *argv[]) qmlRegisterUncreatableType(uri, 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager."); qmlRegisterType(uri, 1, 0, "PluginsProxy"); - qmlRegisterType(uri, 1, 0, "UpnpDiscovery"); - qmlRegisterType(uri, 1, 0, "ZeroconfDiscovery"); + qmlRegisterType(uri, 1, 0, "GuhDiscovery"); + qmlRegisterUncreatableType(uri, 1, 0, "DiscoveryModel", "Get it from GuhDiscovery"); qmlRegisterType(uri, 1, 0, "LogsModel"); qmlRegisterType(uri, 1, 0, "ValueLogsProxyModel"); diff --git a/guh-control/ui/ConnectPage.qml b/guh-control/ui/ConnectPage.qml index 82edbd7a..78fba0ba 100644 --- a/guh-control/ui/ConnectPage.qml +++ b/guh-control/ui/ConnectPage.qml @@ -6,17 +6,15 @@ import Guh 1.0 import "components" Page { + id: root + + readonly property bool haveHosts: discovery.discoveryModel.count > 0 Component.onCompleted: { print("completed connectPage. last connected host:", settings.lastConnectedHost) if (settings.lastConnectedHost.length > 0) { - internalPageStack.push(connectingPage) + pageStack.push(connectingPage) Engine.connection.connect(settings.lastConnectedHost) - } else if (discovery.discoveryModel.count <= 1) { - discovery.discover() - } else { - internalPageStack.pop(); - internalPageStack.push(searchResultsPage) } } @@ -28,176 +26,100 @@ Page { certDialog.fingerprint = fingerprint certDialog.open(); } - onConnectionError: { - discovery.discover(); - } } + ColumnLayout { + anchors.fill: parent + anchors.topMargin: app.bigMargins + spacing: app.margins - Connections { - target: discovery + ColumnLayout { + Layout.fillWidth: true + Layout.margins: app.margins + spacing: app.margins - onDiscoveringChanged: { - print("discoverying changed", discovery.discovering) - if (discovery.discovering) { - internalPageStack.pop(); - } else { - switch (discovery.discoveryModel.count) { - case 0: - internalPageStack.push(noResultsPage); - break; - case 1: - Engine.connection.connect(discovery.discoveryModel.get(0, "guhRpcUrl")) - internalPageStack.push(connectingPage); - break; - default: - internalPageStack.push(searchResultsPage) - } + Label { + Layout.fillWidth: true + text: root.haveHosts ? "Oh, look!" : "Uh oh" + color: "black" + font.pixelSize: app.largeFont + } + + Label { + Layout.fillWidth: true + text: root.haveHosts ? + qsTr("There are %1 guh boxes in your network! Which one would you like to use?").arg(discovery.discoveryModel.count) + : qsTr("There doesn't seem to be a guh box installed in your network. Please make sure your guh box is correctly set up and connected.") + wrapMode: Text.WordWrap } } - } - StackView { - id: internalPageStack - anchors.fill: parent + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Material.accent + } - initialItem: Page { - ColumnLayout { + ListView { + Layout.fillWidth: true + Layout.fillHeight: true + model: discovery.discoveryModel + clip: true + + delegate: ItemDelegate { + width: parent.width + height: app.delegateHeight + ColumnLayout { + anchors.fill: parent + anchors.margins: app.margins + Label { + text: model.name + } + Label { + text: model.hostAddress + font.pixelSize: app.smallFont + } + } + onClicked: { + print("should connect to", model.guhRpcUrl) + Engine.connection.connect(model.guhRpcUrl) + pageStack.push(connectingPage) + } + } + + Column { anchors.centerIn: parent - width: parent.width - app.margins * 2 spacing: app.margins + visible: !root.haveHosts Label { - Layout.fillWidth: true - text: "Just a second, looking for your guh box..." - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - font.pixelSize: app.largeFont + text: qsTr("Searching for guh boxes...") } BusyIndicator { + running: visible anchors.horizontalCenter: parent.horizontalCenter - running: discovery.discovering } } + } - } - Component { - id: noResultsPage - Page { - ColumnLayout { - anchors.centerIn: parent - width: parent.width - app.margins * 2 - spacing: app.margins + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Material.accent + } - Label { - Layout.fillWidth: true - font.pixelSize: app.largeFont - horizontalAlignment: Text.AlignHCenter - text: "Uh oh!" - } - - Label { - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - text: "There doesn't seem to be a guh box installed in your network. Please make sure your guh box is correctly set up and connected and try searching for it again." - } - Button { - Layout.fillWidth: true - text: "Try again!" - onClicked: discovery.discover() - } + RowLayout { + Layout.fillWidth: true + Layout.margins: app.margins + visible: root.haveHosts + Label { + Layout.fillWidth: true + text: "Not the ones you're looking for? We're looking for more!" + wrapMode: Text.WordWrap } - } - } - - Component { - id: searchResultsPage - - Page { - ColumnLayout { - anchors.fill: parent - anchors.topMargin: app.bigMargins - spacing: app.margins - - ColumnLayout { - Layout.fillWidth: true - Layout.margins: app.margins - spacing: app.margins - - Label { - Layout.fillWidth: true - text: "Oh, look!" - color: "black" - font.pixelSize: app.largeFont - } - - Label { - Layout.fillWidth: true - text: qsTr("There are %1 guh boxes in your network! Which one would you like to use?").arg(discovery.discoveryModel.count) - wrapMode: Text.WordWrap - } - } - - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - color: Material.accent - } - - ListView { - Layout.fillWidth: true - Layout.fillHeight: true - model: discovery.discoveryModel - delegate: ItemDelegate { - width: parent.width - height: app.delegateHeight - ColumnLayout { - anchors.fill: parent - anchors.margins: app.margins - Label { - text: model.name - } - Label { - text: model.hostAddress - font.pixelSize: app.smallFont - } - } - onClicked: { - print("should connect to", model.guhRpcUrl) - Engine.connection.connect(model.guhRpcUrl) - internalPageStack.push(connectingPage) - } - } - } - - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - color: Material.accent - } - - ColumnLayout { - Layout.fillWidth: true - Layout.margins: app.margins - spacing: app.margins - - Label { - Layout.fillWidth: true - text: "Not the ones you're looking for? Try again!" - wrapMode: Text.WordWrap - } - - Button { - text: "Search again!" - Layout.fillWidth: true - onClicked: { - discovery.discover() - } - } - } + BusyIndicator { } } } @@ -248,5 +170,4 @@ Page { Engine.connection.acceptCertificate(certDialog.fingerprint) } } - } diff --git a/guh-control/ui/SettingsPage.qml b/guh-control/ui/SettingsPage.qml index dbfe2580..090e53ae 100644 --- a/guh-control/ui/SettingsPage.qml +++ b/guh-control/ui/SettingsPage.qml @@ -25,11 +25,33 @@ Page { Layout.fillWidth: true Label { Layout.fillWidth: true - text: "Full screen" + text: "View mode" } - CheckBox { - checked: settings.fullscreen - onClicked: settings.fullscreen = checked + ComboBox { + model: ["Windowed", "Maximized", "Fullscreen"] + currentIndex: { + switch (settings.viewMode) { + case ApplicationWindow.Windowed: + return 0; + case ApplicationWindow.Maximized: + return 1; + case ApplicationWindow.FullScreen: + return 2; + } + } + + onCurrentIndexChanged: { + switch (currentIndex) { + case 0: + settings.viewMode = ApplicationWindow.Windowed; + break; + case 1: + settings.viewMode = ApplicationWindow.Maximized; + break; + case 2: + settings.viewMode = ApplicationWindow.FullScreen; + } + } } } RowLayout { diff --git a/guh-control/ui/main.qml b/guh-control/ui/main.qml index ae7140e3..36b33630 100644 --- a/guh-control/ui/main.qml +++ b/guh-control/ui/main.qml @@ -10,7 +10,7 @@ ApplicationWindow { visible: true width: 270 * 1.5 height: 480 * 1.5 - visibility: settings.fullscreen ? ApplicationWindow.FullScreen : ApplicationWindow.Windowed + visibility: settings.viewMode property color guhAccent: "#ff57baae" @@ -29,13 +29,14 @@ ApplicationWindow { Settings { id: settings property string lastConnectedHost: "" - property bool fullscreen: false + property int viewMode: ApplicationWindow.Maximized property bool returnToHome: false property string graphStyle: "bars" } Component.onCompleted: { pageStack.push(Qt.resolvedUrl("ConnectPage.qml")) + discovery.discovering = true } Connections { @@ -68,6 +69,7 @@ ApplicationWindow { function init() { pageStack.clear() + discovery.discovering = false; if (Engine.jsonRpcClient.authenticationRequired || Engine.jsonRpcClient.initialSetupRequired) { var page = pageStack.push(Qt.resolvedUrl("LoginPage.qml")); page.backPressed.connect(function() { @@ -78,6 +80,8 @@ ApplicationWindow { pageStack.push(Qt.resolvedUrl("MainPage.qml")) } else { pageStack.push(Qt.resolvedUrl("ConnectPage.qml")) + print("starting discovery") + discovery.discovering = true; } } @@ -87,14 +91,10 @@ ApplicationWindow { initialItem: Page {} } - UpnpDiscovery { + GuhDiscovery { id: discovery } -// ZeroconfDiscovery { -// id: discovery -// } - Connections { target: Qt.application enabled: Engine.jsonRpcClient.connected && settings.returnToHome