#include "saverwidget.h"
#include "ui_saver.h"
#include "screensaver.h"
#include "deadlinetype.h"
#include "config.h"
#include <QTimer>
#include <QX11Info>
#include <QDateTime>
#include <QSettings>
#include <QFile>
#include <QDebug>
#include <QLocalSocket>
#include <QHash>
#define C_ZERO QLatin1Char('0')
static QString formatTime(qlonglong span)
{
QString ret;
qlonglong days = span / 86400;
if (days > 0) {
ret = QString::number(days) + "d ";
span -= 86400 * days;
}
return ret + QString("%1:%2:%3").arg(span / 3600, 2, 10, C_ZERO).arg((span % 3600) / 60, 2, 10, C_ZERO).arg(span % 60, 2, 10, C_ZERO);
}
SaverWidget::SaverWidget(WId parentWinId, QWidget *parent) :
QWidget(parent),
ui(new Ui::Saver),
_parentWinId(parentWinId),
_logoutDeadline(0),
_shutdownDeadline(0),
_counter(0),
_deadlineType(DeadlineType::Unknown),
_standbyDisabled(false),
_isLocked(false),
_unixSocket(nullptr),
_display(QString::fromLocal8Bit(qgetenv("DISPLAY")))
{
int i = _display.indexOf('.');
if (i != -1) {
_display = _display.left(i);
}
QString qss = Config::getMainQss();
qDebug() << "Applying QSS: " << qss;
this->setStyleSheet(qss);
ui->setupUi(this);
QTimer *t = new QTimer(this);
t->setInterval(1000);
connect(t, &QTimer::timeout, [=]() {
if (_counter % 60 == 0) {
this->reloadValues();
}
if (!_isLocked && _counter % 4 == 0) {
_isLocked = ScreenSaver::isLocked();
}
_counter++;
qlonglong now = QDateTime::currentMSecsSinceEpoch() / 1000;
// Determine what's timing out next (session/schedule)
const DeadlineType *type;
qlonglong remaining = 0;
do {
qlonglong shutdownRemaining = _shutdownDeadline - now;
qlonglong logoutRemaining = _logoutDeadline - now;
if (shutdownRemaining > -330 && (shutdownRemaining < logoutRemaining || logoutRemaining <= -330)) {
type = DeadlineType::Shutdown;
remaining = shutdownRemaining;
} else if (logoutRemaining > -330) {
type = DeadlineType::IdleKill;
remaining = logoutRemaining;
} else {
type = DeadlineType::NoTimeout;
}
} while (0);
if (remaining < 0) {
remaining = 0;
}
ui->lblHeader->setText(type->headerLine(_isLocked).arg(formatTime(remaining)));
ui->lblClock->setText(QDateTime::currentDateTime().toString(QLocale().dateFormat() + " HH:mm "));
if (_deadlineType != type) {
_deadlineType = type;
ui->lblText->setText(type->bodyText(_isLocked));
}
bool shouldDisable = (remaining > 0 && remaining < 310);
if (_standbyDisabled != shouldDisable) {
_standbyDisabled = shouldDisable;
if (shouldDisable) {
ScreenSaver::allowSaverAndStandby(false);
ScreenSaver::forceScreenOn();
} else {
ScreenSaver::allowSaverAndStandby(true);
}
}
});
t->start();
reloadValues();
}
SaverWidget::~SaverWidget()
{
delete ui;
}
void SaverWidget::reloadValues()
{
if (_unixSocket != nullptr) {
_unixSocket->blockSignals(true);
_unixSocket->deleteLater();
}
_unixSocket = new QLocalSocket();
connect(_unixSocket, &QLocalSocket::connected, [=]() {
qDebug() << "Connected to daewmweon";
_unixSocket->write((QLatin1String("get ") + _display).toLocal8Bit());
QTimer::singleShot(1000, [this]() {
_unixSocket->disconnectFromServer();
});
});
connect(_unixSocket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), [=](QLocalSocket::LocalSocketError err) {
qDebug() << "Local socket error:" << err;
});
connect(_unixSocket, &QLocalSocket::disconnected, this, &SaverWidget::parseDaemonData);
_unixSocket->connectToServer("/run/idle-daemon");
}
void SaverWidget::parseDaemonData()
{
QTextStream ts(_unixSocket);
QString line;
#define SEC_NONE 0
#define SEC_GENERAL 1
#define SEC_ME 2
#define STORE(x) else if (key == QLatin1String( #x )) x = value.toString()
int sec = SEC_NONE;
QString nextAction, nextActionTime, logoutTime, locked;
while (!ts.atEnd()) {
line = ts.readLine();
if (line.isEmpty())
continue;
if (line.at(0) == QLatin1Char('[')) {
// Section
if (line == QLatin1String("[General]")) {
sec = SEC_GENERAL;
} else if ( line == "[" + _display + "]") {
sec = SEC_ME;
} else {
sec = SEC_NONE;
}
} else {
// Value
int i = line.indexOf(QLatin1Char('='));
if (i == -1)
continue;
const QStringRef key(&line, 0, i);
const QStringRef value(&line, i+ 1, line.size() - (i + 1));
if (sec == SEC_GENERAL) {
if (false);
STORE(nextAction);
STORE(nextActionTime);
} else if (sec == SEC_ME) {
if (false);
STORE(logoutTime);
STORE(locked);
}
}
}
if (nextAction.isEmpty() || nextAction == QLatin1String("none") || nextActionTime.isEmpty()) {
_shutdownDeadline = 0;
} else {
_shutdownDeadline = nextActionTime.toLongLong();
}
_logoutDeadline = logoutTime.toLongLong();
if (!_isLocked && locked.toInt() != 0) {
_isLocked = true;
}
// TODO: Load text strings for everything
_deadlineType = DeadlineType::Unknown;
}