0

I built a small GUI that has shutdown feature after 1 minute. There is a count down that the user can see. The GUI could be left open and inactive if the user does not interact with it of course.

The problem I have is that I am trying to reset the QTimer back to 60 seconds every time the user interacts with the GUI after 5 seconds of inactivity. How do I do that?

Below and here a small verifiable example that shows only a count down time implemented in a QLabel, I know from official documentation that the proper way to do it is to re implement QCoreApplication::notify and that is what I did but something is still not working as expected and I don't see the count down resetting to 60 seconds after I move the mouse after a period of inactivity of 5 seconds.

The minimal code below is perfectly compiling with no errors. You can copy/paste on your machine:

mainwindow.h

#include <QMainWindow>
#include <QTime>
#include <QTimer>
#include <QProcess>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void stopAtZeroCountDown();

public slots:
    void timerUpdate();
private:
    Ui::MainWindow *ui;
    QTimer *timer;
    QTime time;
    QProcess *stopAtZero;
};

#include <QApplication>
class QMyApplication : public QApplication
{
    Q_OBJECT
public:
    QTimer m_timer;
    QMyApplication(int &argc, char **argv) : QApplication(argc,argv)
    {
        m_timer.setInterval(5000);
        connect(&m_timer, SIGNAL(timeout()), this, SLOT(inactive()));
        m_timer.start();
    }
public slots:
    void inactive() {
        m_timer.stop();
    }
protected:
    bool notify ( QObject * receiver, QEvent * event )
    {
        if (event->type() == QEvent::MouseMove || event->type() == QEvent::KeyPress) {
             m_timer.stop(); // reset timer
             m_timer.start();
        }
        return QApplication::notify(receiver, event);
    };
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //stopAtZeroCountDown();
    ui->countDown->setText("1:00");
    time.setHMS(0,1,0);
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate()));
    timer->start(1000);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::stopAtZeroCountDown()
{
    this->stopAtZero->execute(QStringLiteral("/bin/sh"), QStringList() << QStringLiteral("/home/emanuele/catkin_docking_ws/src/lidarboatsproject/stop_lidar_deck_and_gui.sh"));
}

void MainWindow::timerUpdate()
{
    time = time.addSecs(-1);
    ui->countDown->setText(time.toString("mm:ss"));
    // Check if we have a zero time 00:00 on the count down
    if (time == QTime(0, 0)) {
        stopAtZeroCountDown();
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

The errors I am getting and how I am trying to solve them:

The majority of the errors I am gettings are in the last impementation of the protected function as below:

protected:
    bool QMyApplication::notify ( QObject * receiver, QEvent * event ) // <-- Error here
    {
        if (event->type() == QEvent::MouseMove || event->type() == QEvent::KeyPress) {
             m_timer.stop(); // reset timer
             m_timer.start();
        }
        return QApplicaiton::notify(receiver, event);   // <-- Error here
    };

1) I solved the bool QMyApplication::notify ( QObject * receiver, QEvent * event ) error by just declaring the notify function in the following way:

    bool notify ( QObject * receiver, QEvent * event ) // <-- This way I solved it

2) But for the last error what I tried was to return the QMyApplication::notify instead the return QApplicaiton::notify but gave the warning that "All path through this function will call itself"

        return QMyApplication::notify(receiver, event);   // <-- Still error here

How could I fix this and reset the QTimer back to 60 seconds every time the user interacts with the GUI after 5 seconds of inactivity? Thanks for pointing to the right direction for solving this issue.

Emanuele
  • 2,194
  • 6
  • 32
  • 71
  • And you are sure that it's not the typo which is the actual issue? Instead of `return QApplicaiton::notify(receiver, event); // <-- Error here`, it should be `return QApplication::notify(receiver, event);`. – Scheff's Cat Jun 10 '20 at 14:33
  • Your second approach `return QMyApplication::notify(receiver, event);` in `QMyApplication::notify()` would result in a direct and unconditional recursion. It's very kind of your compiler to warn you about this. :-) – Scheff's Cat Jun 10 '20 at 14:35
  • Hello @Scheff and thanks for stopping by....Yes :) the error is the typo....right under my nose and didn't see that....!!! – Emanuele Jun 10 '20 at 14:38
  • Concerning the other error: You used the class scope `QMyApplication::` although the member function is implemented inline. Change this to `bool notify ( QObject * receiver, QEvent * event )`. I guess that's what the complaining about "qualifying" wanted to tell you. – Scheff's Cat Jun 10 '20 at 14:38
  • Let me try that fix on my major application and get back to you! Thanks so far for taking the time to read the question. – Emanuele Jun 10 '20 at 14:40
  • Ok I tried to the small verifiable example first and despite it compiles with no errors. After 5 seconds of inactivity if I move the mouse, the count down does not go back to 1:00 minute. Do you see something I don't see? – Emanuele Jun 10 '20 at 14:51
  • I updated the question with the MVE compiling and my bitbucket [here](https://bitbucket.org/ERaggi/timer/src/master/) if you have time to take a look. Thank you for catching the typo before :) – Emanuele Jun 10 '20 at 14:55
  • After a short look: I saw the timer for inactivity (in `QMyApplication`) and I saw the timer for count down in `MainWindow`. What I missed: In `QMyApplication::notify()` the inactivity timer is restarted. Wouldn't it be a good place to reset the count down of main window as well? Furthermore: The count down timer is started in `MainWindow::MainWindow()`. Wouldn't it be better to start it in `QMyApplication::inactive()` (and to stop it in `QMyApplication::notify()` if activity is detected)? – Scheff's Cat Jun 10 '20 at 15:21
  • Ok so if I understand your suggestion right, you are advising to use either `MainWindow` or `QMyApplication` for both timer correct? Which in this case it would be better to move the count down timer from `MainWindow` to `QMyApplication`? and basically commenting out the `MainWindow` part. correct? – Emanuele Jun 10 '20 at 15:45

0 Answers0