summaryrefslogblamecommitdiffstats
path: root/src/saverwidget.cpp
blob: 5a138dc91ea0ab7deb879cc483d6425d7d0375cf (plain) (tree)

















































































































































































                                                                                                                                                      
#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);
    */
}