rework discovery

This commit is contained in:
Michael Zanetti 2018-02-21 13:16:05 +01:00
parent 46ab4656b4
commit 15cdd7c91c
11 changed files with 198 additions and 220 deletions

View File

@ -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;
}

View File

@ -0,0 +1,35 @@
#ifndef GUHDISCOVERY_H
#define GUHDISCOVERY_H
#include <QObject>
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

View File

@ -24,19 +24,15 @@
#include <QUrl> #include <QUrl>
#include <QXmlStreamReader> #include <QXmlStreamReader>
UpnpDiscovery::UpnpDiscovery(QObject *parent) : UpnpDiscovery::UpnpDiscovery(DiscoveryModel *discoveryModel, QObject *parent) :
QUdpSocket(parent), QUdpSocket(parent),
m_discoveryModel(discoveryModel),
m_discovering(false), m_discovering(false),
m_available(false) m_available(false)
{ {
m_networkAccessManager = new QNetworkAccessManager(this); m_networkAccessManager = new QNetworkAccessManager(this);
connect(m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpnpDiscovery::networkReplyFinished); 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); m_repeatTimer.setInterval(500);
connect(&m_repeatTimer, &QTimer::timeout, this, &UpnpDiscovery::writeDiscoveryPacket); connect(&m_repeatTimer, &QTimer::timeout, this, &UpnpDiscovery::writeDiscoveryPacket);
@ -69,11 +65,6 @@ bool UpnpDiscovery::discovering() const
return m_discovering; return m_discovering;
} }
DiscoveryModel *UpnpDiscovery::discoveryModel()
{
return m_discoveryModel;
}
bool UpnpDiscovery::available() const bool UpnpDiscovery::available() const
{ {
return m_available; return m_available;
@ -87,7 +78,6 @@ void UpnpDiscovery::discover()
} }
qDebug() << "start discovering..."; qDebug() << "start discovering...";
m_timer.start();
m_repeatTimer.start(); m_repeatTimer.start();
// m_discoveryModel->clearModel(); // m_discoveryModel->clearModel();
m_foundDevices.clear(); m_foundDevices.clear();
@ -100,9 +90,7 @@ void UpnpDiscovery::discover()
void UpnpDiscovery::stopDiscovery() void UpnpDiscovery::stopDiscovery()
{ {
qDebug() << "stop discovering"; qDebug() << "stop discovering";
m_timer.stop();
m_repeatTimer.stop(); m_repeatTimer.stop();
m_discoveryModel->clearModel();
setDiscovering(false); setDiscovering(false);
} }
@ -268,10 +256,3 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
reply->deleteLater(); reply->deleteLater();
} }
void UpnpDiscovery::onTimeout()
{
qDebug() << "discovery timeout";
m_repeatTimer.stop();
setDiscovering(false);
}

View File

@ -33,15 +33,10 @@
class UpnpDiscovery : public QUdpSocket class UpnpDiscovery : public QUdpSocket
{ {
Q_OBJECT 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: public:
explicit UpnpDiscovery(QObject *parent = 0); explicit UpnpDiscovery(DiscoveryModel *discoveryModel, QObject *parent = 0);
bool discovering() const; bool discovering() const;
DiscoveryModel *discoveryModel();
bool available() const; bool available() const;
@ -51,7 +46,6 @@ public:
private: private:
QNetworkAccessManager *m_networkAccessManager; QNetworkAccessManager *m_networkAccessManager;
QTimer m_timer;
QTimer m_repeatTimer; QTimer m_repeatTimer;
QHostAddress m_host; QHostAddress m_host;
@ -77,8 +71,6 @@ private slots:
void error(QAbstractSocket::SocketError error); void error(QAbstractSocket::SocketError error);
void readData(); void readData();
void networkReplyFinished(QNetworkReply *reply); void networkReplyFinished(QNetworkReply *reply);
void onTimeout();
}; };
#endif // UPNPDISCOVERY_H #endif // UPNPDISCOVERY_H

View File

@ -3,10 +3,10 @@
#include <QUuid> #include <QUuid>
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 #ifdef WITH_AVAHI
m_serviceBrowser = new QtAvahiServiceBrowser(this); m_serviceBrowser = new QtAvahiServiceBrowser(this);
connect(m_serviceBrowser, &QtAvahiServiceBrowser::serviceEntryAdded, this, &ZeroconfDiscovery::serviceEntryAdded); connect(m_serviceBrowser, &QtAvahiServiceBrowser::serviceEntryAdded, this, &ZeroconfDiscovery::serviceEntryAdded);
@ -28,10 +28,6 @@ bool ZeroconfDiscovery::discovering() const
return true; return true;
} }
DiscoveryModel *ZeroconfDiscovery::discoveryModel() const
{
return m_discoveryModel;
}
#ifdef WITH_AVAHI #ifdef WITH_AVAHI
void ZeroconfDiscovery::serviceEntryAdded(const AvahiServiceEntry &entry) void ZeroconfDiscovery::serviceEntryAdded(const AvahiServiceEntry &entry)
{ {

View File

@ -12,23 +12,13 @@
class ZeroconfDiscovery : public QObject class ZeroconfDiscovery : public QObject
{ {
Q_OBJECT 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: public:
explicit ZeroconfDiscovery(QObject *parent = nullptr); explicit ZeroconfDiscovery(DiscoveryModel *discoveryModel, QObject *parent = nullptr);
bool available() const; bool available() const;
bool discovering() const; bool discovering() const;
DiscoveryModel* discoveryModel() const;
signals:
void discoveringChanged();
public slots:
private: private:
DiscoveryModel *m_discoveryModel; DiscoveryModel *m_discoveryModel;

View File

@ -34,7 +34,8 @@ HEADERS += engine.h \
rulemanager.h \ rulemanager.h \
models/rulesfiltermodel.h \ models/rulesfiltermodel.h \
models/logsmodel.h \ models/logsmodel.h \
models/valuelogsproxymodel.h models/valuelogsproxymodel.h \
discovery/guhdiscovery.h
SOURCES += main.cpp \ SOURCES += main.cpp \
@ -64,7 +65,8 @@ SOURCES += main.cpp \
rulemanager.cpp \ rulemanager.cpp \
models/rulesfiltermodel.cpp \ models/rulesfiltermodel.cpp \
models/logsmodel.cpp \ models/logsmodel.cpp \
models/valuelogsproxymodel.cpp models/valuelogsproxymodel.cpp \
discovery/guhdiscovery.cpp
withavahi { withavahi {
DEFINES += WITH_AVAHI DEFINES += WITH_AVAHI

View File

@ -30,8 +30,8 @@
#include "devicesproxy.h" #include "devicesproxy.h"
#include "pluginsproxy.h" #include "pluginsproxy.h"
#include "devicediscovery.h" #include "devicediscovery.h"
#include "discovery/upnpdiscovery.h" #include "discovery/guhdiscovery.h"
#include "discovery/zeroconfdiscovery.h" #include "discovery/discoverymodel.h"
#include "interfacesmodel.h" #include "interfacesmodel.h"
#include "rulemanager.h" #include "rulemanager.h"
#include "models/rulesfiltermodel.h" #include "models/rulesfiltermodel.h"
@ -112,8 +112,8 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<Plugins>(uri, 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager."); qmlRegisterUncreatableType<Plugins>(uri, 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager.");
qmlRegisterType<PluginsProxy>(uri, 1, 0, "PluginsProxy"); qmlRegisterType<PluginsProxy>(uri, 1, 0, "PluginsProxy");
qmlRegisterType<UpnpDiscovery>(uri, 1, 0, "UpnpDiscovery"); qmlRegisterType<GuhDiscovery>(uri, 1, 0, "GuhDiscovery");
qmlRegisterType<ZeroconfDiscovery>(uri, 1, 0, "ZeroconfDiscovery"); qmlRegisterUncreatableType<DiscoveryModel>(uri, 1, 0, "DiscoveryModel", "Get it from GuhDiscovery");
qmlRegisterType<LogsModel>(uri, 1, 0, "LogsModel"); qmlRegisterType<LogsModel>(uri, 1, 0, "LogsModel");
qmlRegisterType<ValueLogsProxyModel>(uri, 1, 0, "ValueLogsProxyModel"); qmlRegisterType<ValueLogsProxyModel>(uri, 1, 0, "ValueLogsProxyModel");

View File

@ -6,17 +6,15 @@ import Guh 1.0
import "components" import "components"
Page { Page {
id: root
readonly property bool haveHosts: discovery.discoveryModel.count > 0
Component.onCompleted: { Component.onCompleted: {
print("completed connectPage. last connected host:", settings.lastConnectedHost) print("completed connectPage. last connected host:", settings.lastConnectedHost)
if (settings.lastConnectedHost.length > 0) { if (settings.lastConnectedHost.length > 0) {
internalPageStack.push(connectingPage) pageStack.push(connectingPage)
Engine.connection.connect(settings.lastConnectedHost) 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.fingerprint = fingerprint
certDialog.open(); certDialog.open();
} }
onConnectionError: {
discovery.discover();
}
} }
ColumnLayout {
anchors.fill: parent
anchors.topMargin: app.bigMargins
spacing: app.margins
Connections { ColumnLayout {
target: discovery Layout.fillWidth: true
Layout.margins: app.margins
spacing: app.margins
onDiscoveringChanged: { Label {
print("discoverying changed", discovery.discovering) Layout.fillWidth: true
if (discovery.discovering) { text: root.haveHosts ? "Oh, look!" : "Uh oh"
internalPageStack.pop(); color: "black"
} else { font.pixelSize: app.largeFont
switch (discovery.discoveryModel.count) { }
case 0:
internalPageStack.push(noResultsPage); Label {
break; Layout.fillWidth: true
case 1: text: root.haveHosts ?
Engine.connection.connect(discovery.discoveryModel.get(0, "guhRpcUrl")) qsTr("There are %1 guh boxes in your network! Which one would you like to use?").arg(discovery.discoveryModel.count)
internalPageStack.push(connectingPage); : 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.")
break; wrapMode: Text.WordWrap
default:
internalPageStack.push(searchResultsPage)
}
} }
} }
}
StackView { Rectangle {
id: internalPageStack Layout.fillWidth: true
anchors.fill: parent Layout.preferredHeight: 1
color: Material.accent
}
initialItem: Page { ListView {
ColumnLayout { 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 anchors.centerIn: parent
width: parent.width - app.margins * 2
spacing: app.margins spacing: app.margins
visible: !root.haveHosts
Label { Label {
Layout.fillWidth: true text: qsTr("Searching for guh boxes...")
text: "Just a second, looking for your guh box..."
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
font.pixelSize: app.largeFont
} }
BusyIndicator { BusyIndicator {
running: visible
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
running: discovery.discovering
} }
} }
} }
}
Component { Rectangle {
id: noResultsPage Layout.fillWidth: true
Page { Layout.preferredHeight: 1
ColumnLayout { color: Material.accent
anchors.centerIn: parent }
width: parent.width - app.margins * 2
spacing: app.margins
Label { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
font.pixelSize: app.largeFont Layout.margins: app.margins
horizontalAlignment: Text.AlignHCenter visible: root.haveHosts
text: "Uh oh!" Label {
} Layout.fillWidth: true
text: "Not the ones you're looking for? We're looking for more!"
Label { wrapMode: Text.WordWrap
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()
}
} }
} BusyIndicator {
}
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()
}
}
}
} }
} }
} }
@ -248,5 +170,4 @@ Page {
Engine.connection.acceptCertificate(certDialog.fingerprint) Engine.connection.acceptCertificate(certDialog.fingerprint)
} }
} }
} }

View File

@ -25,11 +25,33 @@ Page {
Layout.fillWidth: true Layout.fillWidth: true
Label { Label {
Layout.fillWidth: true Layout.fillWidth: true
text: "Full screen" text: "View mode"
} }
CheckBox { ComboBox {
checked: settings.fullscreen model: ["Windowed", "Maximized", "Fullscreen"]
onClicked: settings.fullscreen = checked 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 { RowLayout {

View File

@ -10,7 +10,7 @@ ApplicationWindow {
visible: true visible: true
width: 270 * 1.5 width: 270 * 1.5
height: 480 * 1.5 height: 480 * 1.5
visibility: settings.fullscreen ? ApplicationWindow.FullScreen : ApplicationWindow.Windowed visibility: settings.viewMode
property color guhAccent: "#ff57baae" property color guhAccent: "#ff57baae"
@ -29,13 +29,14 @@ ApplicationWindow {
Settings { Settings {
id: settings id: settings
property string lastConnectedHost: "" property string lastConnectedHost: ""
property bool fullscreen: false property int viewMode: ApplicationWindow.Maximized
property bool returnToHome: false property bool returnToHome: false
property string graphStyle: "bars" property string graphStyle: "bars"
} }
Component.onCompleted: { Component.onCompleted: {
pageStack.push(Qt.resolvedUrl("ConnectPage.qml")) pageStack.push(Qt.resolvedUrl("ConnectPage.qml"))
discovery.discovering = true
} }
Connections { Connections {
@ -68,6 +69,7 @@ ApplicationWindow {
function init() { function init() {
pageStack.clear() pageStack.clear()
discovery.discovering = false;
if (Engine.jsonRpcClient.authenticationRequired || Engine.jsonRpcClient.initialSetupRequired) { if (Engine.jsonRpcClient.authenticationRequired || Engine.jsonRpcClient.initialSetupRequired) {
var page = pageStack.push(Qt.resolvedUrl("LoginPage.qml")); var page = pageStack.push(Qt.resolvedUrl("LoginPage.qml"));
page.backPressed.connect(function() { page.backPressed.connect(function() {
@ -78,6 +80,8 @@ ApplicationWindow {
pageStack.push(Qt.resolvedUrl("MainPage.qml")) pageStack.push(Qt.resolvedUrl("MainPage.qml"))
} else { } else {
pageStack.push(Qt.resolvedUrl("ConnectPage.qml")) pageStack.push(Qt.resolvedUrl("ConnectPage.qml"))
print("starting discovery")
discovery.discovering = true;
} }
} }
@ -87,14 +91,10 @@ ApplicationWindow {
initialItem: Page {} initialItem: Page {}
} }
UpnpDiscovery { GuhDiscovery {
id: discovery id: discovery
} }
// ZeroconfDiscovery {
// id: discovery
// }
Connections { Connections {
target: Qt.application target: Qt.application
enabled: Engine.jsonRpcClient.connected && settings.returnToHome enabled: Engine.jsonRpcClient.connected && settings.returnToHome