summaryrefslogtreecommitdiffstats
path: root/src/saverwidget.cpp
blob: 5a138dc91ea0ab7deb879cc483d6425d7d0375cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#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);
    */
}