added dyn. api credentials optaining
This commit is contained in:
parent
df59d45e83
commit
bc2ff5b7be
@ -63,13 +63,6 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
|
|||||||
{
|
{
|
||||||
qCDebug(dcTado()) << "Confirm pairing" << username << "Network manager available" << hardwareManager()->networkManager()->available();
|
qCDebug(dcTado()) << "Confirm pairing" << username << "Network manager available" << hardwareManager()->networkManager()->available();
|
||||||
Tado *tado = new Tado(hardwareManager()->networkManager(), username, this);
|
Tado *tado = new Tado(hardwareManager()->networkManager(), username, this);
|
||||||
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
|
|
||||||
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
|
|
||||||
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
|
|
||||||
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
|
|
||||||
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
|
|
||||||
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
|
|
||||||
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
|
|
||||||
m_unfinishedTadoAccounts.insert(info->thingId(), tado);
|
m_unfinishedTadoAccounts.insert(info->thingId(), tado);
|
||||||
|
|
||||||
connect(info, &ThingPairingInfo::aborted, this, [info, tado, this]() {
|
connect(info, &ThingPairingInfo::aborted, this, [info, tado, this]() {
|
||||||
@ -78,13 +71,18 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
|
|||||||
tado->deleteLater();
|
tado->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){
|
connect(tado, &Tado::connectionError, info, [info] (QNetworkReply::NetworkError error){
|
||||||
if (error != QNetworkReply::NetworkError::NoError){
|
if (error != QNetworkReply::NetworkError::NoError){
|
||||||
info->finish(Thing::ThingErrorSetupFailed);
|
qCWarning(dcTado()) << "Confirm pairing failed" << error;
|
||||||
|
info->finish(Thing::ThingErrorSetupFailed, tr("Connection error"));
|
||||||
}
|
}
|
||||||
// info->finish(success) will be called after the token has been received
|
// info->finish(success) will be called after the token has been received
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(tado, &Tado::apiCredentialsReceived, info, [password, tado] {
|
||||||
|
tado->getToken(password);
|
||||||
|
});
|
||||||
|
|
||||||
connect(tado, &Tado::tokenReceived, info, [this, info, username, password](Tado::Token token) {
|
connect(tado, &Tado::tokenReceived, info, [this, info, username, password](Tado::Token token) {
|
||||||
Q_UNUSED(token)
|
Q_UNUSED(token)
|
||||||
|
|
||||||
@ -95,7 +93,7 @@ void IntegrationPluginTado::confirmPairing(ThingPairingInfo *info, const QString
|
|||||||
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
});
|
});
|
||||||
tado->getToken(password);
|
tado->getApiCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
||||||
@ -109,7 +107,7 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
|||||||
if (m_unfinishedTadoAccounts.contains(thing->id())) {
|
if (m_unfinishedTadoAccounts.contains(thing->id())) {
|
||||||
tado = m_unfinishedTadoAccounts.take(thing->id());
|
tado = m_unfinishedTadoAccounts.take(thing->id());
|
||||||
m_tadoAccounts.insert(thing->id(), tado);
|
m_tadoAccounts.insert(thing->id(), tado);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
} else {
|
} else {
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
QString username = pluginStorage()->value("username").toString();
|
QString username = pluginStorage()->value("username").toString();
|
||||||
@ -117,14 +115,6 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
|||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
|
|
||||||
tado = new Tado(hardwareManager()->networkManager(), username, this);
|
tado = new Tado(hardwareManager()->networkManager(), username, this);
|
||||||
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
|
|
||||||
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
|
|
||||||
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
|
|
||||||
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
|
|
||||||
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
|
|
||||||
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
|
|
||||||
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
|
|
||||||
|
|
||||||
m_tadoAccounts.insert(thing->id(), tado);
|
m_tadoAccounts.insert(thing->id(), tado);
|
||||||
connect(info, &ThingSetupInfo::aborted, [info, this] {
|
connect(info, &ThingSetupInfo::aborted, [info, this] {
|
||||||
if (m_tadoAccounts.contains(info->thing()->id())) {
|
if (m_tadoAccounts.contains(info->thing()->id())) {
|
||||||
@ -133,7 +123,11 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(tado, &Tado::tokenReceived, info, [this, info, tado](Tado::Token token) {
|
connect(tado, &Tado::apiCredentialsReceived, info, [password, tado] {
|
||||||
|
tado->getToken(password);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(tado, &Tado::tokenReceived, info, [ info](Tado::Token token) {
|
||||||
Q_UNUSED(token)
|
Q_UNUSED(token)
|
||||||
|
|
||||||
qCDebug(dcTado()) << "Token received, account setup successfull";
|
qCDebug(dcTado()) << "Token received, account setup successfull";
|
||||||
@ -141,18 +135,7 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){
|
connect(tado, &Tado::connectionError, info, [this, info] (QNetworkReply::NetworkError error){
|
||||||
if (error == QNetworkReply::NetworkError::HostNotFoundError) {
|
if (error != QNetworkReply::NetworkError::NoError){
|
||||||
QTimer::singleShot(2000, info, [info, this] {
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(info->thing()->id().toString());
|
|
||||||
QString password = pluginStorage()->value("password").toString();
|
|
||||||
pluginStorage()->endGroup();
|
|
||||||
if (m_tadoAccounts.contains(info->thing()->id())) {
|
|
||||||
Tado *tado = m_tadoAccounts.take(info->thing()->id());
|
|
||||||
tado->getToken(password);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (error != QNetworkReply::NetworkError::NoError){
|
|
||||||
if (m_tadoAccounts.contains(info->thing()->id())) {
|
if (m_tadoAccounts.contains(info->thing()->id())) {
|
||||||
Tado *tado = m_tadoAccounts.take(info->thing()->id());
|
Tado *tado = m_tadoAccounts.take(info->thing()->id());
|
||||||
tado->deleteLater();
|
tado->deleteLater();
|
||||||
@ -160,15 +143,23 @@ void IntegrationPluginTado::setupThing(ThingSetupInfo *info)
|
|||||||
info->finish(Thing::ThingErrorSetupFailed);
|
info->finish(Thing::ThingErrorSetupFailed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tado->getToken(password);
|
tado->getApiCredentials();
|
||||||
}
|
}
|
||||||
|
connect(tado, &Tado::authenticationStatusChanged, this, &IntegrationPluginTado::onAuthenticationStatusChanged);
|
||||||
|
connect(tado, &Tado::requestExecuted, this, &IntegrationPluginTado::onRequestExecuted);
|
||||||
|
connect(tado, &Tado::connectionChanged, this, &IntegrationPluginTado::onConnectionChanged);
|
||||||
|
connect(tado, &Tado::homesReceived, this, &IntegrationPluginTado::onHomesReceived);
|
||||||
|
connect(tado, &Tado::zonesReceived, this, &IntegrationPluginTado::onZonesReceived);
|
||||||
|
connect(tado, &Tado::zoneStateReceived, this, &IntegrationPluginTado::onZoneStateReceived);
|
||||||
|
connect(tado, &Tado::overlayReceived, this, &IntegrationPluginTado::onOverlayReceived);
|
||||||
|
return;
|
||||||
|
|
||||||
} else if (thing->thingClassId() == zoneThingClassId) {
|
} else if (thing->thingClassId() == zoneThingClassId) {
|
||||||
qCDebug(dcTado) << "Setup tado thermostat" << thing->params();
|
qCDebug(dcTado) << "Setup tado thermostat" << thing->params();
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
return info->finish(Thing::ThingErrorNoError);
|
||||||
} else {
|
} else {
|
||||||
return info->finish(Thing::ThingErrorThingClassNotFound);
|
|
||||||
qCWarning(dcTado()) << "Unhandled thing class in setupDevice";
|
qCWarning(dcTado()) << "Unhandled thing class in setupDevice";
|
||||||
|
return info->finish(Thing::ThingErrorThingClassNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,11 @@ QString Tado::username()
|
|||||||
return m_username;
|
return m_username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tado::apiAvailable()
|
||||||
|
{
|
||||||
|
return m_apiAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
bool Tado::authenticated()
|
bool Tado::authenticated()
|
||||||
{
|
{
|
||||||
return m_authenticationStatus;
|
return m_authenticationStatus;
|
||||||
@ -66,8 +71,61 @@ bool Tado::connected()
|
|||||||
return m_connectionStatus;
|
return m_connectionStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tado::getApiCredentials(const QString &url)
|
||||||
|
{
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(url);
|
||||||
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
qCDebug(dcTado()) << "Sending request" << request.url();
|
||||||
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
// Check HTTP status code
|
||||||
|
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||||
|
qCWarning(dcTado()) << "Request error:" << status << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QRegExp filter;
|
||||||
|
filter.setPatternSyntax(QRegExp::Wildcard);
|
||||||
|
filter.setPattern("*tgaRestApiV2Endpoint:*");
|
||||||
|
|
||||||
|
QStringList list = QString(reply->readAll()).split('\n');
|
||||||
|
int index = list.indexOf(filter);
|
||||||
|
if (index == -1)
|
||||||
|
return;
|
||||||
|
m_baseControlUrl = list.value(index).split(": ").last().remove(QRegExp("[,']"));;
|
||||||
|
qCDebug(dcTado()) << "Received control url" << m_baseControlUrl;
|
||||||
|
filter.setPattern("*apiEndpoint*");
|
||||||
|
index = list.indexOf(filter);
|
||||||
|
if (index == -1)
|
||||||
|
return;
|
||||||
|
m_baseAuthorizationUrl = list.value(index).split(": ").last().remove(QRegExp("[,']"))+"/token";
|
||||||
|
qCDebug(dcTado()) << "Received auth url" << m_baseAuthorizationUrl;
|
||||||
|
filter.setPattern("*clientId*");
|
||||||
|
index = list.indexOf(filter);
|
||||||
|
if (index == -1)
|
||||||
|
return;
|
||||||
|
m_clientId = list.value(index).split(": ").last().remove(QRegExp("[,']"));
|
||||||
|
qCDebug(dcTado()) << "Received client id" << m_clientId;
|
||||||
|
filter.setPattern("*clientSecret*");
|
||||||
|
index = list.indexOf(filter);
|
||||||
|
if (index == -1)
|
||||||
|
return;
|
||||||
|
m_clientSecret = list.value(index).split(": ").last().remove(QRegExp("[,']"));
|
||||||
|
qCDebug(dcTado()) << "Received client secret" << m_clientSecret;
|
||||||
|
m_apiAvailable = true;
|
||||||
|
emit apiCredentialsReceived();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Tado::getToken(const QString &password)
|
void Tado::getToken(const QString &password)
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(m_baseAuthorizationUrl));
|
request.setUrl(QUrl(m_baseAuthorizationUrl));
|
||||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
@ -102,7 +160,7 @@ void Tado::getToken(const QString &password)
|
|||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
if (error.error != QJsonParseError::NoError) {
|
if (error.error != QJsonParseError::NoError) {
|
||||||
qDebug(dcTado()) << "Get Token: Received invalide JSON object";
|
qDebug(dcTado()) << "Get Token: Received invalide JSON object:" << data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.isObject()) {
|
if (data.isObject()) {
|
||||||
@ -137,6 +195,11 @@ void Tado::getToken(const QString &password)
|
|||||||
|
|
||||||
void Tado::getHomes()
|
void Tado::getHomes()
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_accessToken.isEmpty()) {
|
if(m_accessToken.isEmpty()) {
|
||||||
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
||||||
return;
|
return;
|
||||||
@ -188,6 +251,16 @@ void Tado::getHomes()
|
|||||||
|
|
||||||
void Tado::getZones(const QString &homeId)
|
void Tado::getZones(const QString &homeId)
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_accessToken.isEmpty()) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones"));
|
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones"));
|
||||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
@ -235,10 +308,16 @@ void Tado::getZones(const QString &homeId)
|
|||||||
|
|
||||||
void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_accessToken.isEmpty()) {
|
if(m_accessToken.isEmpty()) {
|
||||||
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/state"));
|
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/state"));
|
||||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
@ -307,10 +386,16 @@ void Tado::getZoneState(const QString &homeId, const QString &zoneId)
|
|||||||
|
|
||||||
QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature)
|
QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power, double targetTemperature)
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
if(m_accessToken.isEmpty()) {
|
if(m_accessToken.isEmpty()) {
|
||||||
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid requestId = QUuid::createUuid();
|
QUuid requestId = QUuid::createUuid();
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
||||||
@ -376,10 +461,16 @@ QUuid Tado::setOverlay(const QString &homeId, const QString &zoneId, bool power,
|
|||||||
|
|
||||||
QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId)
|
QUuid Tado::deleteOverlay(const QString &homeId, const QString &zoneId)
|
||||||
{
|
{
|
||||||
|
if (!m_apiAvailable) {
|
||||||
|
qCWarning(dcTado()) << "Not sending request, get API credentials firs";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
if(m_accessToken.isEmpty()) {
|
if(m_accessToken.isEmpty()) {
|
||||||
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
qCWarning(dcTado()) << "Not sending request, get the access token first";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid requestId = QUuid::createUuid();
|
QUuid requestId = QUuid::createUuid();
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
request.setUrl(QUrl(m_baseControlUrl+"/homes/"+homeId+"/zones/"+zoneId+"/overlay"));
|
||||||
|
|||||||
12
tado/tado.h
12
tado/tado.h
@ -93,9 +93,11 @@ public:
|
|||||||
|
|
||||||
void setUsername(const QString &username);
|
void setUsername(const QString &username);
|
||||||
QString username();
|
QString username();
|
||||||
|
bool apiAvailable();
|
||||||
bool authenticated();
|
bool authenticated();
|
||||||
bool connected();
|
bool connected();
|
||||||
|
|
||||||
|
void getApiCredentials(const QString &url = "https://my.tado.com/webapp/env.js");
|
||||||
void getToken(const QString &password);
|
void getToken(const QString &password);
|
||||||
void getHomes();
|
void getHomes();
|
||||||
void getZones(const QString &homeId);
|
void getZones(const QString &homeId);
|
||||||
@ -105,10 +107,11 @@ public:
|
|||||||
QUuid deleteOverlay(const QString &homeId, const QString &zoneId);
|
QUuid deleteOverlay(const QString &homeId, const QString &zoneId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray m_baseAuthorizationUrl = "https://auth.tado.com/oauth/token";
|
bool m_apiAvailable = false;
|
||||||
QByteArray m_baseControlUrl = "https://my.tado.com/api/v2";
|
QString m_baseAuthorizationUrl;
|
||||||
QByteArray m_clientSecret = "4HJGRffVR8xb3XdEUQpjgZ1VplJi6Xgw";
|
QString m_baseControlUrl;
|
||||||
QByteArray m_clientId = "public-api-preview";
|
QString m_clientSecret;
|
||||||
|
QString m_clientId;
|
||||||
|
|
||||||
NetworkAccessManager *m_networkManager = nullptr;
|
NetworkAccessManager *m_networkManager = nullptr;
|
||||||
QString m_username;
|
QString m_username;
|
||||||
@ -123,6 +126,7 @@ private:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged(bool connected);
|
void connectionChanged(bool connected);
|
||||||
|
void apiCredentialsReceived();
|
||||||
void authenticationStatusChanged(bool authenticated);
|
void authenticationStatusChanged(bool authenticated);
|
||||||
void requestExecuted(QUuid requestId, bool success);
|
void requestExecuted(QUuid requestId, bool success);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user