spacetray/spacetray.cpp

131 lines
4 KiB
C++

#include "spacetray.h"
#include "themes/lock.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkRequest>
#include <QAction>
#include <QCoreApplication>
#include <QImage>
#include <QPixmap>
#include <QDebug>
SpaceTray::SpaceTray(const QString &url, QObject *parent)
: QObject(parent),
m_statusUrl(url),
m_doorOpen(false),
m_oldDoorOpen(false),
m_doorLastChange(0),
m_spaceName("Unknown Space"),
m_firstRun(true)
{
// Initialize icons from raw data
QImage imgOpen(icon_open_data, 52, 48, 208, QImage::Format_RGBA8888);
m_iconOpen = QIcon(QPixmap::fromImage(imgOpen));
QImage imgClosed(icon_closed_data, 52, 48, 208, QImage::Format_RGBA8888);
m_iconClosed = QIcon(QPixmap::fromImage(imgClosed));
// Setup tray icon
m_trayIcon = new QSystemTrayIcon(this);
m_trayIcon->setIcon(m_iconClosed);
m_trayIcon->setVisible(true);
// Setup tray menu
m_trayMenu = new QMenu();
QAction *quitAction = m_trayMenu->addAction("Quit");
connect(quitAction, &QAction::triggered, this, &SpaceTray::quit);
m_trayIcon->setContextMenu(m_trayMenu);
connect(m_trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
if (reason == QSystemTrayIcon::Trigger) {
fetchData();
}
});
// Setup network manager
m_networkManager = new QNetworkAccessManager(this);
// Setup timer (300 seconds as per previous delay=300 in C code)
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &SpaceTray::fetchData);
m_timer->start(300000); // 300 seconds in ms
// Initial fetch
fetchData();
}
SpaceTray::~SpaceTray()
{
delete m_trayMenu;
}
void SpaceTray::fetchData()
{
QNetworkRequest request(m_statusUrl);
request.setHeader(QNetworkRequest::UserAgentHeader, "Spacetray/0.42 (Qt)");
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, &QNetworkReply::finished, this, [this, reply]() { onFinished(reply); });
}
void SpaceTray::onFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Network error:" << reply->errorString();
reply->deleteLater();
return;
}
QByteArray data = reply->readAll();
reply->deleteLater();
// Remove UTF-8 BOM if present
if (data.startsWith("\xEF\xBB\xBF")) {
data.remove(0, 3);
}
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
if (doc.isNull()) {
qWarning() << "Failed to parse JSON:" << error.errorString();
qWarning() << "Raw data:" << data;
return;
}
QJsonObject obj = doc.object();
m_spaceName = obj.value("space").toString("Unknown Space");
QJsonObject stateObj = obj.value("state").toObject();
m_oldDoorOpen = m_doorOpen;
m_doorOpen = stateObj.value("open").toBool();
m_doorLastChange = stateObj.value("lastchange").toVariant().toLongLong();
updateTray();
if (!m_firstRun && m_doorOpen != m_oldDoorOpen) {
QString dateStr = QDateTime::fromSecsSinceEpoch(m_doorLastChange).toString("yyyy-MM-dd HH:mm:ss");
QString status = m_doorOpen ? "open" : "closed";
showNotification(QString("%1: Door %2 since %3").arg(m_spaceName, status, dateStr));
}
m_firstRun = false;
}
void SpaceTray::updateTray()
{
m_trayIcon->setIcon(m_doorOpen ? m_iconOpen : m_iconClosed);
QString dateStr = QDateTime::fromSecsSinceEpoch(m_doorLastChange).toString("yyyy-MM-dd HH:mm:ss");
QString status = m_doorOpen ? "open" : "closed";
QString tooltip = QString("%1: Door %2 since %3").arg(m_spaceName, status, dateStr);
m_trayIcon->setToolTip(tooltip);
}
void SpaceTray::showNotification(const QString &message)
{
m_trayIcon->showMessage("SpaceAPI widget for UNIX", message, m_doorOpen ? m_iconOpen : m_iconClosed);
}
void SpaceTray::quit()
{
QCoreApplication::quit();
}