- idle tracking - initial implementation
This commit is contained in:
parent
18ac04ec18
commit
d2d899280d
@ -4,7 +4,7 @@
|
||||
// App version
|
||||
#define QBREAK_VERSION_MAJOR 0
|
||||
#define QBREAK_VERSION_MINOR 1
|
||||
#define QBREAK_VERSION_SUFFIX 0
|
||||
#define QBREAK_VERSION_SUFFIX 1
|
||||
|
||||
// How often UI is updated - interval in seconds
|
||||
#define INTERVAL_UPDATE_UI (60)
|
||||
|
||||
37
app/idle_tracking.cpp
Normal file
37
app/idle_tracking.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "idle_tracking.h"
|
||||
#include "settings.h"
|
||||
#if defined(TARGET_LINUX)
|
||||
|
||||
// Thanks to https://stackoverflow.com/questions/222606/detecting-keyboard-mouse-activity-in-linux
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
|
||||
|
||||
int get_idle_time()
|
||||
{
|
||||
time_t idle_time;
|
||||
static XScreenSaverInfo *mit_info;
|
||||
Display *display;
|
||||
int screen;
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
if ((display = XOpenDisplay(NULL)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
|
||||
idle_time = (mit_info->idle) / 1000 / 60;
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
7
app/idle_tracking.h
Normal file
7
app/idle_tracking.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __IDLE_TRACKING_H
|
||||
#define __IDLE_TRACKING_H
|
||||
|
||||
// Returns the idle time in minutes
|
||||
extern int get_idle_time();
|
||||
|
||||
#endif
|
||||
@ -6,6 +6,7 @@
|
||||
#include "aboutdlg.h"
|
||||
#include "config.h"
|
||||
#include "audio_support.h"
|
||||
#include "idle_tracking.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
@ -78,18 +79,19 @@ void MainWindow::init()
|
||||
// No postpone attempts yet
|
||||
mPostponeCount = 0;
|
||||
|
||||
// Timer
|
||||
// Timer to start break
|
||||
mTimer = new QTimer(this);
|
||||
mTimer->setTimerType(Qt::TimerType::CoarseTimer);
|
||||
mTimer->setSingleShot(true);
|
||||
connect(mTimer, SIGNAL(timeout()), this, SLOT(onLongBreakStart()));
|
||||
|
||||
// Timer to run notification about upcoming break
|
||||
mNotifyTimer = new QTimer(this);
|
||||
mNotifyTimer->setTimerType(Qt::TimerType::CoarseTimer);
|
||||
mNotifyTimer->setSingleShot(true);
|
||||
connect(mNotifyTimer, SIGNAL(timeout()), this, SLOT(onLongBreakNotify()));
|
||||
|
||||
|
||||
// Just update UI once per minute
|
||||
mUpdateUITimer = new QTimer(this);
|
||||
mUpdateUITimer->setTimerType(Qt::TimerType::CoarseTimer);
|
||||
mUpdateUITimer->setSingleShot(false);
|
||||
@ -97,6 +99,7 @@ void MainWindow::init()
|
||||
connect(mUpdateUITimer, SIGNAL(timeout()), this, SLOT(onUpdateUI()));
|
||||
mUpdateUITimer->start();
|
||||
|
||||
// Timer to draw progress bar during the break
|
||||
mProgressTimer = new QTimer(this);
|
||||
mProgressTimer->setInterval(std::chrono::milliseconds(INTERVAL_UPDATE_PROGRESS));
|
||||
mProgressTimer->setSingleShot(false);
|
||||
@ -269,6 +272,25 @@ void MainWindow::onUpdateUI()
|
||||
}
|
||||
|
||||
ui->mSkipButton->setVisible(mPostponeCount > 0);
|
||||
|
||||
if (mAppConfig.idle_timeout != 0)
|
||||
{
|
||||
int idle_minutes = get_idle_time();
|
||||
if (idle_minutes >= mAppConfig.idle_timeout)
|
||||
{
|
||||
// Idle mode is active. Increase the timer interval
|
||||
mIdleStart = std::chrono::steady_clock::now() - std::chrono::minutes(idle_minutes);
|
||||
|
||||
int remaining_minutes = mTimer->remainingTime() / 1000 / 60;
|
||||
|
||||
// Change the time
|
||||
mTimer->stop();
|
||||
mTimer->start(std::chrono::minutes(remaining_minutes + idle_minutes));
|
||||
|
||||
qDebug() << "Idle detected for " << idle_minutes << " minutes. "
|
||||
<< "Remaining " << mTimer->remainingTime() / 1000 / 60 << " until the next break.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onLongBreakNotify()
|
||||
|
||||
@ -39,6 +39,7 @@ private:
|
||||
std::chrono::steady_clock::time_point mBreakStartTime;
|
||||
app_settings::config mAppConfig;
|
||||
int mPostponeCount;
|
||||
std::chrono::steady_clock::time_point mIdleStart;
|
||||
|
||||
void init();
|
||||
void loadConfig();
|
||||
|
||||
@ -16,7 +16,8 @@ SOURCES += \
|
||||
settings.cpp \
|
||||
settingsdialog.cpp \
|
||||
runguard.cpp \
|
||||
audio_support.cpp
|
||||
audio_support.cpp \
|
||||
idle_tracking.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
@ -27,7 +28,8 @@ HEADERS += \
|
||||
settings.h \
|
||||
settingsdialog.h \
|
||||
runguard.h \
|
||||
audio_support.h
|
||||
audio_support.h \
|
||||
idle_tracking.h
|
||||
|
||||
|
||||
FORMS += \
|
||||
@ -45,3 +47,7 @@ unix:!macx: DEFINES += TARGET_LINUX
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
unix:LIBS += -L/usr/X11R6/lib/ -lX11 -lXext -lXss
|
||||
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ const QString Key_PreferredMonitor = "Preferred_Monitor";
|
||||
const QString Key_Audio_Name = "Audio_Name";
|
||||
const QString Key_Audio_Path = "Audio_Path";
|
||||
const QString Key_Script = "Script";
|
||||
const QString Key_Idle_Timeout = "Idle_Timeout";
|
||||
|
||||
void app_settings::save(const config &cfg)
|
||||
{
|
||||
@ -28,6 +29,7 @@ void app_settings::save(const config &cfg)
|
||||
s.setValue(Key_Audio_Name, cfg.play_audio.name);
|
||||
s.setValue(Key_Audio_Path, cfg.play_audio.path);
|
||||
s.setValue(Key_Script, cfg.script_on_break_finish);
|
||||
s.setValue(Key_Idle_Timeout, cfg.idle_timeout);
|
||||
}
|
||||
|
||||
app_settings::config app_settings::load()
|
||||
@ -45,6 +47,7 @@ app_settings::config app_settings::load()
|
||||
r.play_audio.name = s.value(Key_Audio_Name, Audio_Empty).toString();
|
||||
r.play_audio.path = s.value(Key_Audio_Path, QString()).toString();
|
||||
r.script_on_break_finish = s.value(Key_Script, QString()).toString();
|
||||
r.idle_timeout = s.value(Key_Idle_Timeout, Default_Idle_Timeout).toInt();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -19,6 +19,9 @@ const bool Default_Verbose = false;
|
||||
// Default autostart
|
||||
const bool Default_Autostart = true;
|
||||
|
||||
// Default idle timeout
|
||||
const int Default_Idle_Timeout = 0;
|
||||
|
||||
const QString Default_Monitor = "";
|
||||
const QString Primary_Monitor = "[Primary]";
|
||||
|
||||
@ -67,6 +70,9 @@ public:
|
||||
// This value can be path to audio file or empty or [embedded] string
|
||||
selected_audio play_audio;
|
||||
QString script_on_break_finish;
|
||||
|
||||
// Zero means "idle is not tracked"
|
||||
int idle_timeout = Default_Idle_Timeout;
|
||||
};
|
||||
|
||||
static void save(const config& cfg);
|
||||
|
||||
@ -69,6 +69,9 @@ void SettingsDialog::init()
|
||||
ui->mScriptEdit->setText(c.script_on_break_finish);
|
||||
connect(ui->mAudioComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onAudioIndexChanged(int)));
|
||||
|
||||
// Idle timeout
|
||||
ui->mIdleTimeoutSpinbox->setValue(c.idle_timeout);
|
||||
|
||||
mSkipAudioChangeEvent = false;
|
||||
}
|
||||
|
||||
@ -87,6 +90,7 @@ void SettingsDialog::accept()
|
||||
if (c.play_audio.name == Audio_Custom)
|
||||
c.play_audio.path = mCustomAudioPath;
|
||||
|
||||
c.idle_timeout = ui->mIdleTimeoutSpinbox->value();
|
||||
app_settings::save(c);
|
||||
|
||||
emit accepted();
|
||||
|
||||
@ -138,6 +138,20 @@
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="mScriptEdit"/>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Idle timeout in minutes (zero means no idle tracking)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="mIdleTimeoutSpinbox">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user