Cupidvogel
29th December 2015, 15:43
I need to find out when my app is idle for say 20 seconds, and then do something. The logic I thought of is this: run a timer constantly with timeout set to 20 seconds, on any user action, cancel the timer and start it again. Then I found this code here (http://blog.surgeons.org.uk/2010/08/detecting-application-idle-in-qt-4.html) do the same thing. This is the code:
#include "IdleTimer.hpp"
// Static initialisers
IdleTimer *IdleTimer::m_Instance = 0;
QTimer *IdleTimer::m_timer = new QTimer();
int IdleTimer::m_timeout = 0;
QMutex IdleTimer::m_timeoutMutex;
/*!
* Class constructor
*/
IdleTimer::IdleTimer(QObject *parent, int seconds) :
QObject(parent)
{
m_timeoutMutex.lock();
if (seconds)
m_timeout = seconds;
Q_ASSERT(parent);
Q_ASSERT_X(m_timeout, "IdleTimer Constructor", "The timeout must be specified in the first call to instance.");
parent->installEventFilter(this);
m_timer->singleShot(m_timeout*1000, this, SLOT(idleTimeout()));
m_timeoutMutex.unlock();
}
/*!
* Either reset the timeout to a different value to restart the timer
*/
void IdleTimer::start(int seconds/*=0*/) {
m_timeoutMutex.lock();
if(seconds)
m_timeout = seconds;
Q_ASSERT_X(m_timeout, "IdleTimer reset", "A timeout must be specified either in this call or in the first call to instance.");
m_timer->start(m_timeout*1000);
m_timeoutMutex.unlock();
}
void IdleTimer::stop() {
m_timeoutMutex.lock();
m_timer->stop();
m_timeoutMutex.unlock();
}
/*!
* The vent filter
*/
bool IdleTimer::eventFilter(QObject *obj, QEvent *ev)
{
qDebug() << "Ah, caught!" << endl;
if(ev->type() == QEvent::KeyPress ||
ev->type() == QEvent::MouseMove)
// now reset your timer, for example
IdleTimer::m_timer->start();
// Must return to allow further processing
return QObject::eventFilter(obj, ev);
}
// Must return to allow further processing
return QObject::eventFilter(obj, ev);
}
/*slot*/
void IdleTimer::idleTimeout() {
qDebug("Application has been idle, emitting idle signal ...");
emit idle();
}
Header:
#ifndef IDLETIMER_H
#define IDLETIMER_H
#include <qobject>
#include <qmutex>
#include <qevent>
#include <qtimer>
class IdleTimer : public QObject
{
Q_OBJECT
public:
// Singleton class stuff
static IdleTimer* instance(QObject *parent=0, int seconds=0) {
static QMutex mutex;
if (!m_Instance) {
mutex.lock();
m_Instance = new IdleTimer(parent, seconds);
mutex.unlock();
}
return m_Instance;
}
static void drop() {
qDebug("IdleTimer dropped ...");
static QMutex mutex;
mutex.lock();
m_timer->stop();
if(m_timer) delete m_timer;
if (m_Instance)
delete m_Instance;
m_Instance = 0;
mutex.unlock();
}
void start(int seconds = 0);
void stop();
private:
explicit IdleTimer(QObject *parent, int seconds);
explicit IdleTimer() {}
~IdleTimer() {}
IdleTimer(const IdleTimer &); // hide copy constructor
IdleTimer& operator=(const IdleTimer &); // hide assign op
static IdleTimer *m_Instance;
static QTimer *m_timer;
static QMutex m_timeoutMutex;
static int m_timeout;
signals:
void idle();
private slots:
void idleTimeout();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
};
#endif // IDLETIMER_H
This is how I am using this (MyApplication extends QApplication)
MyApplication:: MyApplication()
{
IdleTimer* timer = IdleTimer::instance(this,20);
}
The problem is on app launch, whatever happens, whether I am active or idle, the Application has been idle, emitting idle signal ... gets printed after the first 20 seconds. Moving the mouse, clicking somewhere does not cancel the timer and restart it. But the qDebug within event-filter works correctly on moving/clicking, which means the event filter is working fine, code is coming upto that point, but somehow I am not able to restart the timer as expected.
How do I fix this?
#include "IdleTimer.hpp"
// Static initialisers
IdleTimer *IdleTimer::m_Instance = 0;
QTimer *IdleTimer::m_timer = new QTimer();
int IdleTimer::m_timeout = 0;
QMutex IdleTimer::m_timeoutMutex;
/*!
* Class constructor
*/
IdleTimer::IdleTimer(QObject *parent, int seconds) :
QObject(parent)
{
m_timeoutMutex.lock();
if (seconds)
m_timeout = seconds;
Q_ASSERT(parent);
Q_ASSERT_X(m_timeout, "IdleTimer Constructor", "The timeout must be specified in the first call to instance.");
parent->installEventFilter(this);
m_timer->singleShot(m_timeout*1000, this, SLOT(idleTimeout()));
m_timeoutMutex.unlock();
}
/*!
* Either reset the timeout to a different value to restart the timer
*/
void IdleTimer::start(int seconds/*=0*/) {
m_timeoutMutex.lock();
if(seconds)
m_timeout = seconds;
Q_ASSERT_X(m_timeout, "IdleTimer reset", "A timeout must be specified either in this call or in the first call to instance.");
m_timer->start(m_timeout*1000);
m_timeoutMutex.unlock();
}
void IdleTimer::stop() {
m_timeoutMutex.lock();
m_timer->stop();
m_timeoutMutex.unlock();
}
/*!
* The vent filter
*/
bool IdleTimer::eventFilter(QObject *obj, QEvent *ev)
{
qDebug() << "Ah, caught!" << endl;
if(ev->type() == QEvent::KeyPress ||
ev->type() == QEvent::MouseMove)
// now reset your timer, for example
IdleTimer::m_timer->start();
// Must return to allow further processing
return QObject::eventFilter(obj, ev);
}
// Must return to allow further processing
return QObject::eventFilter(obj, ev);
}
/*slot*/
void IdleTimer::idleTimeout() {
qDebug("Application has been idle, emitting idle signal ...");
emit idle();
}
Header:
#ifndef IDLETIMER_H
#define IDLETIMER_H
#include <qobject>
#include <qmutex>
#include <qevent>
#include <qtimer>
class IdleTimer : public QObject
{
Q_OBJECT
public:
// Singleton class stuff
static IdleTimer* instance(QObject *parent=0, int seconds=0) {
static QMutex mutex;
if (!m_Instance) {
mutex.lock();
m_Instance = new IdleTimer(parent, seconds);
mutex.unlock();
}
return m_Instance;
}
static void drop() {
qDebug("IdleTimer dropped ...");
static QMutex mutex;
mutex.lock();
m_timer->stop();
if(m_timer) delete m_timer;
if (m_Instance)
delete m_Instance;
m_Instance = 0;
mutex.unlock();
}
void start(int seconds = 0);
void stop();
private:
explicit IdleTimer(QObject *parent, int seconds);
explicit IdleTimer() {}
~IdleTimer() {}
IdleTimer(const IdleTimer &); // hide copy constructor
IdleTimer& operator=(const IdleTimer &); // hide assign op
static IdleTimer *m_Instance;
static QTimer *m_timer;
static QMutex m_timeoutMutex;
static int m_timeout;
signals:
void idle();
private slots:
void idleTimeout();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
};
#endif // IDLETIMER_H
This is how I am using this (MyApplication extends QApplication)
MyApplication:: MyApplication()
{
IdleTimer* timer = IdleTimer::instance(this,20);
}
The problem is on app launch, whatever happens, whether I am active or idle, the Application has been idle, emitting idle signal ... gets printed after the first 20 seconds. Moving the mouse, clicking somewhere does not cancel the timer and restart it. But the qDebug within event-filter works correctly on moving/clicking, which means the event filter is working fine, code is coming upto that point, but somehow I am not able to restart the timer as expected.
How do I fix this?