Fix refresh time and add refresh schedule configuration

This commit is contained in:
Simon Stürz 2018-02-15 14:21:04 +01:00 committed by Michael Zanetti
parent 9e75362850
commit 9abc0982cb
7 changed files with 193 additions and 78 deletions

View File

@ -30,19 +30,26 @@ DevicePluginSnapd::DevicePluginSnapd()
} }
DevicePluginSnapd::~DevicePluginSnapd()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
hardwareManager()->pluginTimerManager()->unregisterTimer(m_updateTimer);
}
void DevicePluginSnapd::init() void DevicePluginSnapd::init()
{ {
// Check advanced mode // Initialize plugin configurations
m_advancedMode = configValue(SnapdAdvancedModeParamTypeId).toBool(); m_advancedMode = configValue(SnapdAdvancedModeParamTypeId).toBool();
m_refreshTime = configValue(SnapdRefreshScheduleParamTypeId).toInt();
connect(this, &DevicePluginSnapd::configValueChanged, this, &DevicePluginSnapd::onPluginConfigurationChanged); connect(this, &DevicePluginSnapd::configValueChanged, this, &DevicePluginSnapd::onPluginConfigurationChanged);
// Setup timers // Refresh timer for snapd checks
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2); m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginSnapd::onRefreshTimer); connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginSnapd::onRefreshTimer);
// Check all 5 min if there is an update available // Check all 4 hours if there is an update available
m_updateTimer = hardwareManager()->pluginTimerManager()->registerTimer(300); m_updateTimer = hardwareManager()->pluginTimerManager()->registerTimer(14400);
connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginSnapd::onUpdateTimer); connect(m_updateTimer, &PluginTimer::timeout, this, &DevicePluginSnapd::onUpdateTimer);
} }
void DevicePluginSnapd::startMonitoringAutoDevices() void DevicePluginSnapd::startMonitoringAutoDevices()
@ -69,9 +76,9 @@ void DevicePluginSnapd::startMonitoringAutoDevices()
void DevicePluginSnapd::postSetupDevice(Device *device) void DevicePluginSnapd::postSetupDevice(Device *device)
{ {
if (m_snapdControl && m_snapdControl->device() == device) if (m_snapdControl && m_snapdControl->device() == device) {
m_snapdControl->update(); m_snapdControl->update();
}
} }
void DevicePluginSnapd::deviceRemoved(Device *device) void DevicePluginSnapd::deviceRemoved(Device *device)
@ -107,6 +114,7 @@ DeviceManager::DeviceSetupStatus DevicePluginSnapd::setupDevice(Device *device)
} }
m_snapdControl = new SnapdControl(device, this); m_snapdControl = new SnapdControl(device, this);
m_snapdControl->setPreferedRefreshTime(configValue(SnapdRefreshScheduleParamTypeId).toInt());
connect(m_snapdControl, &SnapdControl::snapListUpdated, this, &DevicePluginSnapd::onSnapListUpdated); connect(m_snapdControl, &SnapdControl::snapListUpdated, this, &DevicePluginSnapd::onSnapListUpdated);
} else if (device->deviceClassId() == snapDeviceClassId) { } else if (device->deviceClassId() == snapDeviceClassId) {
@ -171,6 +179,9 @@ DeviceManager::DeviceError DevicePluginSnapd::executeAction(Device *device, cons
void DevicePluginSnapd::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value) void DevicePluginSnapd::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value)
{ {
qCDebug(dcSnapd()) << "Plugin configuration changed";
// Check advanced mode
if (paramTypeId == SnapdAdvancedModeParamTypeId) { if (paramTypeId == SnapdAdvancedModeParamTypeId) {
qCDebug(dcSnapd()) << "Advanced mode" << (value.toBool() ? "enabled." : "disabled."); qCDebug(dcSnapd()) << "Advanced mode" << (value.toBool() ? "enabled." : "disabled.");
m_advancedMode = value.toBool(); m_advancedMode = value.toBool();
@ -189,6 +200,16 @@ void DevicePluginSnapd::onPluginConfigurationChanged(const ParamTypeId &paramTyp
m_snapdControl->update(); m_snapdControl->update();
} }
} }
// Check refresh schedule
if (paramTypeId == SnapdRefreshScheduleParamTypeId) {
if (!m_snapdControl)
return;
m_refreshTime = value.toInt();
qCDebug(dcSnapd()) << "Refresh schedule start time" << QTime(m_refreshTime, 0, 0).toString("hh:mm");
m_snapdControl->setPreferedRefreshTime(m_refreshTime);
}
} }
void DevicePluginSnapd::onRefreshTimer() void DevicePluginSnapd::onRefreshTimer()

View File

@ -42,6 +42,8 @@ class DevicePluginSnapd: public DevicePlugin {
public: public:
explicit DevicePluginSnapd(); explicit DevicePluginSnapd();
~DevicePluginSnapd();
void init() override; void init() override;
void startMonitoringAutoDevices() override; void startMonitoringAutoDevices() override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
@ -56,6 +58,7 @@ private:
PluginTimer *m_updateTimer = nullptr; PluginTimer *m_updateTimer = nullptr;
bool m_advancedMode = false; bool m_advancedMode = false;
int m_refreshTime = 2;
// Snap list for faster access (snap id, device) // Snap list for faster access (snap id, device)
QHash<QString, Device *> m_snapDevices; QHash<QString, Device *> m_snapDevices;

View File

@ -9,6 +9,16 @@
"displayName": "Advanced mode", "displayName": "Advanced mode",
"type": "bool", "type": "bool",
"defaultValue": false "defaultValue": false
},
{
"id": "d2e697d1-9a68-4666-bf40-8d70fa694eec",
"name": "refreshSchedule",
"displayName": "Automatic daily refresh schedule",
"type": "int",
"unit": "Hours",
"minValue": 0,
"maxValue": 23,
"defaultValue": 2
} }
], ],
"vendors": [ "vendors": [

View File

@ -39,6 +39,11 @@ SnapdConnection::SnapdConnection(QObject *parent) :
connect(this, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onError(QLocalSocket::LocalSocketError))); connect(this, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onError(QLocalSocket::LocalSocketError)));
} }
SnapdConnection::~SnapdConnection()
{
close();
}
SnapdReply *SnapdConnection::get(const QString &path, QObject *parent) SnapdReply *SnapdConnection::get(const QString &path, QObject *parent)
{ {
SnapdReply *reply = new SnapdReply(parent); SnapdReply *reply = new SnapdReply(parent);
@ -70,6 +75,22 @@ SnapdReply *SnapdConnection::post(const QString &path, const QByteArray &payload
return reply; return reply;
} }
SnapdReply *SnapdConnection::put(const QString &path, const QByteArray &payload, QObject *parent)
{
SnapdReply *reply = new SnapdReply(parent);
reply->setRequestPath(path);
reply->setRequestMethod("PUT");
QByteArray header = createRequestHeader("PUT", path, payload);
reply->setRequestRawMessage(header.append(payload));
// Enqueue the new reply
m_replyQueue.enqueue(reply);
sendNextRequest();
// Note: the caller owns the object now
return reply;
}
bool SnapdConnection::isConnected() const bool SnapdConnection::isConnected() const
{ {
return m_connected; return m_connected;
@ -95,7 +116,7 @@ void SnapdConnection::setConnected(const bool &connected)
while (!m_replyQueue.isEmpty()) { while (!m_replyQueue.isEmpty()) {
QPointer<SnapdReply> reply = m_replyQueue.dequeue(); QPointer<SnapdReply> reply = m_replyQueue.dequeue();
if (!reply.isNull()) { if (!reply.isNull()) {
reply->setFinished(false); reply->deleteLater();
} }
} }
} else { } else {
@ -258,8 +279,10 @@ void SnapdConnection::sendNextRequest()
if (m_debug) if (m_debug)
qCDebug(dcSnapd()) << "-->" << reply->requestMethod() << reply->requestPath(); qCDebug(dcSnapd()) << "-->" << reply->requestMethod() << reply->requestPath();
// If write failes, the reply is finished invalid and the owner has to delete it // Send current reply request. If write failes, the reply is finished invalid and the owner has to delete it
if (write(reply->requestRawMessage()) < 0) { qint64 bytesWritten = write(reply->requestRawMessage());
if (bytesWritten < 0) {
qCWarning(dcSnapd()) << "Could not write request data" << reply->requestMethod() << reply->requestMethod();
m_currentReply->setFinished(false); m_currentReply->setFinished(false);
m_currentReply = nullptr; m_currentReply = nullptr;
sendNextRequest(); sendNextRequest();

View File

@ -34,9 +34,11 @@ class SnapdConnection : public QLocalSocket
Q_OBJECT Q_OBJECT
public: public:
explicit SnapdConnection(QObject *parent = nullptr); explicit SnapdConnection(QObject *parent = nullptr);
~SnapdConnection();
SnapdReply *get(const QString &path, QObject *parent); SnapdReply *get(const QString &path, QObject *parent);
SnapdReply *post(const QString &path, const QByteArray &payload, QObject *parent); SnapdReply *post(const QString &path, const QByteArray &payload, QObject *parent);
SnapdReply *put(const QString &path, const QByteArray &payload, QObject *parent);
bool isConnected() const; bool isConnected() const;

View File

@ -33,6 +33,12 @@ SnapdControl::SnapdControl(Device *device, QObject *parent) :
m_device(device), m_device(device),
m_snapdSocketPath("/run/snapd.socket") m_snapdSocketPath("/run/snapd.socket")
{ {
// If a change is one of following kind, the plugin will recognize it as update running
m_updateChangeKinds.append("install-snap");
m_updateChangeKinds.append("remove-snap");
m_updateChangeKinds.append("refresh-snap");
m_updateChangeKinds.append("revert-snap");
m_snapConnection = new SnapdConnection(this); m_snapConnection = new SnapdConnection(this);
connect(m_snapConnection, &SnapdConnection::connectedChanged, this, &SnapdControl::onConnectedChanged); connect(m_snapConnection, &SnapdConnection::connectedChanged, this, &SnapdControl::onConnectedChanged);
} }
@ -73,6 +79,11 @@ bool SnapdControl::enabled() const
return m_enabled; return m_enabled;
} }
bool SnapdControl::timerBasedSchedule() const
{
return m_timerBasedSchedule;
}
void SnapdControl::loadSystemInfo() void SnapdControl::loadSystemInfo()
{ {
if (!m_snapConnection) if (!m_snapConnection)
@ -109,7 +120,7 @@ void SnapdControl::loadRunningChanges()
connect(reply, &SnapdReply::finished, this, &SnapdControl::onLoadRunningChangesFinished); connect(reply, &SnapdReply::finished, this, &SnapdControl::onLoadRunningChangesFinished);
} }
void SnapdControl::loadChange(const int &change) void SnapdControl::configureRefreshSchedule()
{ {
if (!m_snapConnection) if (!m_snapConnection)
return; return;
@ -117,34 +128,15 @@ void SnapdControl::loadChange(const int &change)
if (!m_snapConnection->isConnected()) if (!m_snapConnection->isConnected())
return; return;
SnapdReply *reply = m_snapConnection->get(QString("/v2/changes/%1").arg(QString::number(change)), this); QVariantMap configuration; QVariantMap configMap;
connect(reply, &SnapdReply::finished, this, &SnapdControl::onLoadChangeFinished); configMap.insert("timer", m_preferedRefreshSchedule);
} configMap.insert("schedule", m_preferedRefreshSchedule);
configuration.insert("refresh", configMap);
void SnapdControl::processChange(const QVariantMap &changeMap) qCDebug(dcSnapd()) << "Configure refresh schedule from" << m_currentRefreshSchedule << "-->" << m_preferedRefreshSchedule;
{
int changeId = changeMap.value("id").toInt();
bool changeReady = changeMap.value("ready").toBool();
QString changeKind = changeMap.value("kind").toString();
QString changeStatus = changeMap.value("status").toString();
QString changeSummary = changeMap.value("summary").toString();
qCDebug(dcSnapd()) << changeStatus << changeKind << changeSummary; SnapdReply *reply = m_snapConnection->put(QString("/v2/snaps/core/conf"), QJsonDocument::fromVariant(configuration).toJson(QJsonDocument::Compact), this);
connect(reply, &SnapdReply::finished, this, &SnapdControl::onConfigureRefreshScheduleFinished);
// Add this change if not already finishished or added
if (!m_watchingChanges.contains(changeId) && !changeReady)
m_watchingChanges.append(changeId);
// If change is on Doing, update the status
if (changeStatus == "Doing") {
device()->setStateValue(snapdControlStatusStateTypeId, changeSummary);
}
// If this change is on ready, we can remove it from our watch list
if (changeReady) {
qCDebug(dcSnapd()).noquote() << changeKind << (changeReady ? "finished." : "running.") << changeSummary;
m_watchingChanges.removeAll(changeId);
}
} }
bool SnapdControl::validAsyncResponse(const QVariantMap &responseMap) bool SnapdControl::validAsyncResponse(const QVariantMap &responseMap)
@ -185,7 +177,23 @@ void SnapdControl::onLoadSystemInfoFinished()
device()->setStateValue(snapdControlLastUpdateTimeStateTypeId, lastRefreshTime.toTime_t()); device()->setStateValue(snapdControlLastUpdateTimeStateTypeId, lastRefreshTime.toTime_t());
device()->setStateValue(snapdControlNextUpdateTimeStateTypeId, nextRefreshTime.toTime_t()); device()->setStateValue(snapdControlNextUpdateTimeStateTypeId, nextRefreshTime.toTime_t());
// Check if we are working on refresh timer or refresh schedule
if (result.value("refresh").toMap().contains("schedule")) {
// Schedule based core snap
m_timerBasedSchedule = false;
m_currentRefreshSchedule = result.value("refresh").toMap().value("schedule").toString();
} else if (result.value("refresh").toMap().contains("timer")) {
// Timer based core snap: snapd >= 2.31
m_timerBasedSchedule = true;
m_currentRefreshSchedule = result.value("refresh").toMap().value("timer").toString();
}
reply->deleteLater(); reply->deleteLater();
// Check if the refresh schedule should be updated
if (m_currentRefreshSchedule != m_preferedRefreshSchedule) {
configureRefreshSchedule();
}
} }
void SnapdControl::onLoadSnapListFinished() void SnapdControl::onLoadSnapListFinished()
@ -210,42 +218,63 @@ void SnapdControl::onLoadRunningChangesFinished()
return; return;
} }
foreach (const QVariant &changeVariant, reply->dataMap().value("result").toList()) { // Load changes list
processChange(changeVariant.toMap()); QVariantList changes = reply->dataMap().value("result").toList();
} reply->deleteLater();
// Check if there are still changes around
if (reply->dataMap().value("result").toList().isEmpty()) {
// If there are no running changes, we can forget old ones
m_watchingChanges.clear();
// If there are no running changes, update is not running
if (changes.isEmpty()) {
// Update not running any more // Update not running any more
device()->setStateValue(snapdControlUpdateRunningStateTypeId, false); device()->setStateValue(snapdControlUpdateRunningStateTypeId, false);
device()->setStateValue(snapdControlStatusStateTypeId, "-"); device()->setStateValue(snapdControlStatusStateTypeId, "-");
} else { return;
// Update running
device()->setStateValue(snapdControlUpdateRunningStateTypeId, true);
} }
reply->deleteLater(); bool updateRunning = false;
QString updateStatus = "-";
// Verifiy if a change is running and which one is currently doing something
foreach (const QVariant &changeVariant, changes) {
QVariantMap changeMap = changeVariant.toMap();
int changeId = changeMap.value("id").toInt();
bool changeReady = changeMap.value("ready").toBool();
QString changeKind = changeMap.value("kind").toString();
QString changeStatus = changeMap.value("status").toString();
QString changeSummary = changeMap.value("summary").toString();
// If there is a change kind "doing" or "Do"
if ( (changeStatus == "Doing" || changeStatus == "Do") && m_updateChangeKinds.contains(changeKind)) {
// Set the status of the current running change
updateRunning = true;
if (changeStatus == "Doing") {
updateStatus = changeSummary;
qCDebug(dcSnapd()).noquote() << "Current change:" << changeId << (changeReady ? "ready" : "not ready") << changeStatus << changeKind << changeSummary;
}
}
}
device()->setStateValue(snapdControlUpdateRunningStateTypeId, updateRunning);
device()->setStateValue(snapdControlStatusStateTypeId, updateStatus);
} }
void SnapdControl::onLoadChangeFinished() void SnapdControl::onConfigureRefreshScheduleFinished()
{ {
SnapdReply *reply = static_cast<SnapdReply *>(sender()); SnapdReply *reply = static_cast<SnapdReply *>(sender());
if (!reply->isValid()) { if (!reply->isValid()) {
qCDebug(dcSnapd()) << "Load change request finished with error" << reply->requestPath(); qCDebug(dcSnapd()) << "Set refresh schedule request finished with error" << reply->requestPath();
reply->deleteLater(); reply->deleteLater();
return; return;
} }
processChange(reply->dataMap().value("result").toMap()); if (!validAsyncResponse(reply->dataMap())) {
qCWarning(dcSnapd()) << "Async refresh configuration request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("status-code").toInt();
if (m_watchingChanges.isEmpty()) { reply->deleteLater();
device()->setStateValue(snapdControlUpdateRunningStateTypeId, false); return;
device()->setStateValue(snapdControlStatusStateTypeId, "-");
} }
qCDebug(dcSnapd()) << "Configure refresh schedule finished successfully";
reply->deleteLater(); reply->deleteLater();
} }
@ -258,11 +287,10 @@ void SnapdControl::onSnapRefreshFinished()
return; return;
} }
//qCDebug(dcSnapd()) << qUtf8Printable(QJsonDocument::fromVariant(reply->dataMap()).toJson(QJsonDocument::Indented));
if (!validAsyncResponse(reply->dataMap())) { if (!validAsyncResponse(reply->dataMap())) {
qCWarning(dcSnapd()) << "Async change request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("").toString(); qCWarning(dcSnapd()) << "Async refresh request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("status-code").toInt();
} else { } else {
loadChange(reply->dataMap().value("change").toInt()); loadRunningChanges();
} }
reply->deleteLater(); reply->deleteLater();
@ -277,12 +305,12 @@ void SnapdControl::onSnapRevertFinished()
return; return;
} }
//qCDebug(dcSnapd()) << qUtf8Printable(QJsonDocument::fromVariant(reply->dataMap()).toJson(QJsonDocument::Indented));
if (!validAsyncResponse(reply->dataMap())) { if (!validAsyncResponse(reply->dataMap())) {
qCWarning(dcSnapd()) << "Async change request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("").toString(); qCWarning(dcSnapd()) << "Async change request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("status-code").toInt();;
} else { } else {
loadChange(reply->dataMap().value("change").toInt()); loadRunningChanges();
} }
reply->deleteLater(); reply->deleteLater();
} }
@ -290,13 +318,26 @@ void SnapdControl::onCheckForUpdatesFinished()
{ {
SnapdReply *reply = static_cast<SnapdReply *>(sender()); SnapdReply *reply = static_cast<SnapdReply *>(sender());
if (!reply->isValid()) { if (!reply->isValid()) {
qCDebug(dcSnapd()) << "Snap check for updates request finished with error" << reply->requestPath(); qCDebug(dcSnapd()) << "Check for snap updates request finished with error" << reply->requestPath();
reply->deleteLater(); reply->deleteLater();
return; return;
} }
//qCDebug(dcSnapd()) << qUtf8Printable(QJsonDocument::fromVariant(reply->dataMap()).toJson(QJsonDocument::Indented)); qCDebug(dcSnapd()) << "Check for available snap updates finished.";
device()->setStateValue(snapdControlUpdateAvailableStateTypeId, !reply->dataMap().value("result").toList().isEmpty()); if (reply->dataMap().value("result").toList().isEmpty()) {
qCDebug(dcSnapd()) << "There are no snap updates available.";
device()->setStateValue(snapdControlUpdateAvailableStateTypeId, false);
} else {
// Print available snap updates
qCDebug(dcSnapd()) << "Following snaps can be updated:";
foreach (const QVariant &resultVariant, reply->dataMap().value("result").toList()) {
QVariantMap resultMap = resultVariant.toMap();
qCDebug(dcSnapd()) << " -->" << resultMap.value("name").toString() << resultMap.value("version").toString();
}
device()->setStateValue(snapdControlUpdateAvailableStateTypeId, true);
}
reply->deleteLater(); reply->deleteLater();
} }
@ -310,10 +351,11 @@ void SnapdControl::onChangeSnapChannelFinished()
} }
if (!validAsyncResponse(reply->dataMap())) { if (!validAsyncResponse(reply->dataMap())) {
qCWarning(dcSnapd()) << "Async change request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("").toString(); qCWarning(dcSnapd()) << "Async change request finished with error" << reply->dataMap().value("status").toString() << reply->dataMap().value("status-code").toInt();
} else { } else {
loadChange(reply->dataMap().value("change").toInt()); loadRunningChanges();
} }
reply->deleteLater(); reply->deleteLater();
} }
@ -354,17 +396,13 @@ void SnapdControl::update()
return; return;
// Update information // Update information
if (!m_watchingChanges.isEmpty()) { if (device()->stateValue(snapdControlUpdateRunningStateTypeId).toBool()) {
// We are watching currently changes // Note: if an update is running, just load the changes to save system resources
foreach (const int &change, m_watchingChanges) {
loadChange(change);
}
loadRunningChanges(); loadRunningChanges();
} else { } else {
// Normal refresh // Normal update
loadSystemInfo(); loadSystemInfo();
loadSnapList(); loadSnapList();
checkForUpdates();
loadRunningChanges(); loadRunningChanges();
} }
} }
@ -410,10 +448,20 @@ void SnapdControl::checkForUpdates()
if (!m_snapConnection->isConnected()) if (!m_snapConnection->isConnected())
return; return;
qCDebug(dcSnapd()) << "Checking for available snap updates";
SnapdReply *reply = m_snapConnection->get("/v2/find?select=refresh", this); SnapdReply *reply = m_snapConnection->get("/v2/find?select=refresh", this);
connect(reply, &SnapdReply::finished, this, &SnapdControl::onCheckForUpdatesFinished); connect(reply, &SnapdReply::finished, this, &SnapdControl::onCheckForUpdatesFinished);
} }
void SnapdControl::setPreferedRefreshTime(int startTime)
{
// Schedule the refresh between startTime and startTime + 59 minutes
QTime start(startTime, 0, 0);
QTime end = start.addSecs(3540);
m_preferedRefreshSchedule = QString("%1-%2").arg(start.toString("h:mm")).arg(end.toString("h:mm"));
qCDebug(dcSnapd()) << "Set prefered refresh schedule to " << m_preferedRefreshSchedule;
}
void SnapdControl::snapRevert(const QString &snapName) void SnapdControl::snapRevert(const QString &snapName)
{ {
if (!m_snapConnection) if (!m_snapConnection)

View File

@ -40,6 +40,7 @@ public:
bool available() const; bool available() const;
bool connected() const; bool connected() const;
bool enabled() const; bool enabled() const;
bool timerBasedSchedule() const;
private: private:
Device *m_device = nullptr; Device *m_device = nullptr;
@ -48,15 +49,19 @@ private:
QString m_snapdSocketPath; QString m_snapdSocketPath;
bool m_enabled = true; bool m_enabled = true;
QList<int> m_watchingChanges; QStringList m_updateChangeKinds;
bool m_timerBasedSchedule = false;
QString m_currentRefreshSchedule;
QString m_preferedRefreshSchedule;
// Update calls // Update calls
void loadSystemInfo(); void loadSystemInfo();
void loadSnapList(); void loadSnapList();
void loadRunningChanges(); void loadRunningChanges();
void loadChange(const int &change);
void processChange(const QVariantMap &changeMap); void configureRefreshSchedule();
bool validAsyncResponse(const QVariantMap &responseMap); bool validAsyncResponse(const QVariantMap &responseMap);
private slots: private slots:
@ -66,7 +71,7 @@ private slots:
void onLoadSystemInfoFinished(); void onLoadSystemInfoFinished();
void onLoadSnapListFinished(); void onLoadSnapListFinished();
void onLoadRunningChangesFinished(); void onLoadRunningChangesFinished();
void onLoadChangeFinished(); void onConfigureRefreshScheduleFinished();
void onSnapRefreshFinished(); void onSnapRefreshFinished();
void onSnapRevertFinished(); void onSnapRevertFinished();
@ -84,6 +89,9 @@ public slots:
void update(); void update();
void snapRefresh(); void snapRefresh();
void checkForUpdates(); void checkForUpdates();
void setPreferedRefreshTime(int startTime);
void snapRevert(const QString &snapName); void snapRevert(const QString &snapName);
void changeSnapChannel(const QString &snapName, const QString &channel); void changeSnapChannel(const QString &snapName, const QString &channel);
}; };