#include "saverwidget.h"
#include "ui_saver.h"
#include "screensaver.h"
#include <QTimer>
#include <QX11Info>
#include <QDateTime>
#include <QSettings>
#include <X11/Xlib.h>
static const QChar C_ZERO('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),
_lastMouseFake(0),
_logoutDeadline(0),
_shutdownDeadline(0),
_counter(0),
_deadlineType(DeadlineType::Unspecified),
_standbyDisabled(false),
_isLocked(false)
{
ui->setupUi(this);
QTimer *t = new QTimer(this);
t->setInterval(1000);
connect(t, &QTimer::timeout, [=]() {
if (_counter % 60 == 0) {
this->reloadValues();
}
if (_counter % 10 == 0) {
_isLocked = ScreenSaver::isLocked();
}
_counter++;
qlonglong now = QDateTime::currentMSecsSinceEpoch() / 1000;
// Determine what's timing out next (session/schedule)
DeadlineType type;
qlonglong remaining = 0;
if (_shutdownDeadline > 0 && _shutdownDeadline < _logoutDeadline) {
type = DeadlineType::Shutdown;
remaining = _shutdownDeadline - now;
} else if (_logoutDeadline > 0) {
type = (_isLocked ? DeadlineType::IdleKillLocked : DeadlineType::IdleKill);
remaining = _logoutDeadline - now;
} else {
type = DeadlineType::Unspecified;
}
if (type == DeadlineType::Shutdown) {
// Shutdown is about to happen (sooner than idle logout)
if (remaining < 0) {
ui->lblHeader->setText(QString("Dieser Rechner ist seit %1 ausgeschaltet (theoretisch zumindest)").arg(formatTime(-remaining)));
} else {
ui->lblHeader->setText(QString("Achtung: Rechner wird in %1 heruntergefahren!").arg(formatTime(remaining)));
}
} else if (type == DeadlineType::IdleKillLocked) {
// Idle logout is about to happen
if (remaining < 0) {
ui->lblHeader->setText("Diese Sitzung kann durch einen Klick auf 'New Login' beendet werden...");
} else {
ui->lblHeader->setText(QString("Diese Sitzung wird in %1 beendet, wenn sie nicht entsperrt wird.").arg(formatTime(remaining)));
}
} else if (type == DeadlineType::IdleKill) {
// Idle logout is about to happen, but password is not required to reactivate session
if (remaining < 0) {
ui->lblHeader->setText("Hier hat wohl jemand vergessen sich auszuloggen...");
} else {
ui->lblHeader->setText(QString("Diese Sitzung wird in %1 beendet, wenn sie nicht weiter verwendet wird.").arg(formatTime(remaining)));
}
} else {
if (_isLocked) {
ui->lblHeader->setText("Rechner gesperrt");
} else {
ui->lblHeader->setText("Schon schon schon...");
}
}
ui->lblClock->setText(QDateTime::currentDateTime().toString(QLocale().dateFormat() + " HH:mm "));
displayText(type);
bool shouldDisable = remaining < 300;
if (_standbyDisabled != shouldDisable) {
_standbyDisabled = shouldDisable;
if (shouldDisable) {
ScreenSaver::allowSaverAndStandby(false);
ScreenSaver::forceScreenOn();
} else {
ScreenSaver::allowSaverAndStandby(true);
}
}
});
t->start();
this->setMouseTracking(true);
reloadValues();
}
SaverWidget::~SaverWidget()
{
delete ui;
}
void SaverWidget::reloadValues()
{
QString display = QString::fromLocal8Bit(qgetenv("DISPLAY"));
int i = display.indexOf('.');
if (i != -1) {
display = display.left(i);
}
QSettings s(QString("/run/idleaction-") + display, QSettings::IniFormat);
_logoutDeadline = s.value("lockDeadline", 0).toLongLong();
_shutdownDeadline = s.value("shutdownDeadline", 0).toLongLong();
// TODO: Load text strings for everything
_deadlineType = DeadlineType::Unspecified;
}
void SaverWidget::displayText(DeadlineType dlt)
{
if (_deadlineType == dlt)
return;
_deadlineType = dlt;
if (dlt == DeadlineType::IdleKillLocked) {
ui->lblText->setText("<html><body><br>"
"Zum oben angegebenen Zeitpunkt wird die aktuell laufende Sitzung beendet, "
"wenn sie zuvor nicht wieder entsperrt wird.<br>"
"Alle noch laufenden Programme (z.B. Word, Photoshop, Matlab, etc.)<br>"
"werden ohne Nachfrage geschlossen. Stellen Sie daher sicher, bis zum angegebenen Zeitpunkt<br>"
"sämtliche sich in Bearbeitung befindlichen Daten abzuspeichern, bzw. die Sitzung wieder zu entsperren.<br><br>"
"Dies dient dazu zu vermeiden, dass ein Rechner stundenlang gesperrt wird und somit<br>"
"anderen Nutzern nicht zur Verfügung steht.</body></html>");
} else if (dlt == DeadlineType::IdleKill) {
ui->lblText->setText("<html><body>Keine Nutzeraktivität festgestellt.<br>"
"Zum oben angegebenen Zeitpunkt wird die aktuell laufende Sitzung beendet, "
"wenn der Rechner nicht mehr verwendet wird.<br>"
"Alle noch laufenden Programme (z.B. Word, Photoshop, Matlab, etc.)<br>"
"werden ohne Nachfrage geschlossen. Stellen Sie daher sicher, bis zum angegebenen Zeitpunkt<br>"
"sämtliche sich in Bearbeitung befindlichen Daten abzuspeichern.<br><br>"
"Dies dient dazu zu vermeiden, dass ein Rechner stundenlang gesperrt wird und somit<br>"
"anderen Nutzern nicht zur Verfügung steht.</body></html>");
} else if (dlt == DeadlineType::Shutdown) {
ui->lblText->setText("<html><body>Achtung: Zum oben angegebenen Zeitpunkt wird der Computer heruntergefahren bzw. neugestartet.<br>"
"Alle noch laufenden Programme (z.B. Word, Photoshop, Matlab, etc.)<br>"
"werden ohne Nachfrage beendet. Stellen Sie daher sicher, bis zum angegebenen Zeitpunkt<br>"
"sämtliche Daten abzuspeichern und die Sitzung zu verlassen.</body></html>");
} else {
ui->lblText->setText("");
}
}
void SaverWidget::mouseMoveEvent(QMouseEvent *)
{
/*
// Doesn't work, method is never called :-(
qint64 now = QDateTime::currentMSecsSinceEpoch();
if (now - _lastMouseFake < 1000)
return;
ui->lblText->setText(QString::number(int(now / 1000)));
_lastMouseFake = now;
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.type = ButtonPress;
ev.xbutton.button = 1;
ev.xbutton.same_screen = True;
ev.xbutton.root = ev.xbutton.window = ev.xbutton.subwindow = _parentWinId;
XSendEvent(QX11Info::display(), _parentWinId, True, 0xfff, &ev);
ev.type = ButtonRelease;
ev.xbutton.state = 0x100;
XSendEvent(QX11Info::display(), _parentWinId, True, 0xfff, &ev);
*/
}