Inactivity lock timeout

This commit is contained in:
tobtoht 2022-03-04 17:20:17 +01:00
parent 4950d659f3
commit 7708cb5705
No known key found for this signature in database
GPG key ID: 1CADD27F41F45C3C
11 changed files with 171 additions and 7 deletions

View file

@ -87,6 +87,11 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
#ifdef DONATE_BEG #ifdef DONATE_BEG
this->donationNag(); this->donationNag();
#endif #endif
connect(m_windowManager->eventFilter, &EventFilter::userActivity, this, &MainWindow::userActivity);
connect(&m_checkUserActivity, &QTimer::timeout, this, &MainWindow::checkUserActivity);
m_checkUserActivity.setInterval(5000);
m_checkUserActivity.start();
} }
void MainWindow::initStatusBar() { void MainWindow::initStatusBar() {
@ -1579,11 +1584,12 @@ void MainWindow::updateRecentlyOpenedMenu() {
bool MainWindow::verifyPassword() { bool MainWindow::verifyPassword() {
bool ok; bool ok;
while (true) { while (true) {
QString password = QInputDialog::getText(this, "Enter password", "Please enter your password:", QLineEdit::EchoMode::Password, "", &ok); PasswordDialog passwordDialog{this->walletName(), false, this};
if (!ok) { // Dialog cancelled int ret = passwordDialog.exec();
if (ret == QDialog::Rejected) {
return false; return false;
} }
if (password != m_ctx->wallet->getPassword()) { if (passwordDialog.password != m_ctx->wallet->getPassword()) {
QMessageBox::warning(this, "Error", "Incorrect password"); QMessageBox::warning(this, "Error", "Incorrect password");
continue; continue;
} }
@ -1600,6 +1606,37 @@ void MainWindow::patchStylesheetMac() {
qApp->setStyleSheet(styleSheet); qApp->setStyleSheet(styleSheet);
} }
void MainWindow::userActivity() {
m_userLastActive = QDateTime::currentSecsSinceEpoch();
}
void MainWindow::checkUserActivity() {
if (!config()->get(Config::inactivityLockEnabled).toBool()) {
return;
}
if (m_constructingTransaction) {
return;
}
if ((m_userLastActive + (config()->get(Config::inactivityLockTimeout).toInt()*60)) < QDateTime::currentSecsSinceEpoch()) {
m_checkUserActivity.stop();
qInfo() << "Locking wallet for inactivity";
if (!this->verifyPassword()) {
this->setEnabled(false);
this->close();
// This doesn't close the wallet immediately.
do {
QApplication::processEvents();
// Because running it a single time is apparently not enough.
// TODO: Qt bug? Need proper fix for this.
} while (QApplication::hasPendingEvents());
} else {
m_checkUserActivity.start();
}
}
}
void MainWindow::toggleSearchbar(bool visible) { void MainWindow::toggleSearchbar(bool visible) {
config()->set(Config::showSearchbar, visible); config()->set(Config::showSearchbar, visible);

View file

@ -30,6 +30,7 @@
#include "model/CoinsProxyModel.h" #include "model/CoinsProxyModel.h"
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/EventFilter.h"
#include "widgets/CCSWidget.h" #include "widgets/CCSWidget.h"
#include "widgets/RedditWidget.h" #include "widgets/RedditWidget.h"
#include "widgets/TickerWidget.h" #include "widgets/TickerWidget.h"
@ -215,6 +216,8 @@ private:
void updateWidgetIcons(); void updateWidgetIcons();
bool verifyPassword(); bool verifyPassword();
void patchStylesheetMac(); void patchStylesheetMac();
void userActivity();
void checkUserActivity();
QIcon hardwareDevicePairedIcon(); QIcon hardwareDevicePairedIcon();
QIcon hardwareDeviceUnpairedIcon(); QIcon hardwareDeviceUnpairedIcon();
@ -260,6 +263,7 @@ private:
QMap<QString, ToggleTab*> m_tabShowHideMapper; QMap<QString, ToggleTab*> m_tabShowHideMapper;
QTimer m_updateBytes; QTimer m_updateBytes;
QTimer m_checkUserActivity;
QString m_statusText; QString m_statusText;
int m_statusDots; int m_statusDots;
@ -269,6 +273,9 @@ private:
QTimer m_txTimer; QTimer m_txTimer;
bool cleanedUp = false; bool cleanedUp = false;
EventFilter *m_eventFilter = nullptr;
qint64 m_userLastActive = QDateTime::currentSecsSinceEpoch();
}; };
#endif // FEATHER_MAINWINDOW_H #endif // FEATHER_MAINWINDOW_H

View file

@ -31,6 +31,12 @@ Settings::Settings(QSharedPointer<AppContext> ctx, QWidget *parent)
config()->set(Config::disableLogging, toggled); config()->set(Config::disableLogging, toggled);
WalletManager::instance()->setLogLevel(toggled ? -1 : config()->get(Config::logLevel).toInt()); WalletManager::instance()->setLogLevel(toggled ? -1 : config()->get(Config::logLevel).toInt());
}); });
connect(ui->checkBox_inactivityLockTimeout, &QCheckBox::toggled, [](bool toggled){
config()->set(Config::inactivityLockEnabled, toggled);
});
connect(ui->spinBox_inactivityLockTimeout, QOverload<int>::of(&QSpinBox::valueChanged), [](int value){
config()->set(Config::inactivityLockTimeout, value);
});
connect(ui->closeButton, &QDialogButtonBox::accepted, this, &Settings::close); connect(ui->closeButton, &QDialogButtonBox::accepted, this, &Settings::close);
@ -44,6 +50,8 @@ Settings::Settings(QSharedPointer<AppContext> ctx, QWidget *parent)
ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool()); ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool());
ui->checkBox_hideBalance->setChecked(config()->get(Config::hideBalance).toBool()); ui->checkBox_hideBalance->setChecked(config()->get(Config::hideBalance).toBool());
ui->checkBox_disableLogging->setChecked(config()->get(Config::disableLogging).toBool()); ui->checkBox_disableLogging->setChecked(config()->get(Config::disableLogging).toBool());
ui->checkBox_inactivityLockTimeout->setChecked(config()->get(Config::inactivityLockEnabled).toBool());
ui->spinBox_inactivityLockTimeout->setValue(config()->get(Config::inactivityLockTimeout).toInt());
// setup comboboxes // setup comboboxes
this->setupSkinCombobox(); this->setupSkinCombobox();

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>915</width> <width>915</width>
<height>519</height> <height>553</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -218,6 +218,60 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QCheckBox" name="checkBox_inactivityLockTimeout">
<property name="text">
<string>Lock wallet on inactivity after</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_inactivityLockTimeout">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>120</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>minutes</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_node"> <widget class="QWidget" name="tab_node">

View file

@ -15,7 +15,9 @@
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
WindowManager::WindowManager() { WindowManager::WindowManager(EventFilter *eventFilter)
: eventFilter(eventFilter)
{
m_walletManager = WalletManager::instance(); m_walletManager = WalletManager::instance();
m_splashDialog = new SplashDialog; m_splashDialog = new SplashDialog;
m_cleanupThread = new QThread(); m_cleanupThread = new QThread();

View file

@ -17,7 +17,7 @@ class WindowManager : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit WindowManager(); explicit WindowManager(EventFilter *eventFilter);
~WindowManager() override; ~WindowManager() override;
void wizardOpenWallet(); void wizardOpenWallet();
@ -28,6 +28,8 @@ public:
void restartApplication(const QString &binaryFilename); void restartApplication(const QString &binaryFilename);
void raise(); void raise();
EventFilter *eventFilter;
signals: signals:
void torSettingsChanged(); void torSettingsChanged();

View file

@ -11,6 +11,7 @@
#include "config-feather.h" #include "config-feather.h"
#include "constants.h" #include "constants.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "utils/EventFilter.h"
#include "WindowManager.h" #include "WindowManager.h"
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
@ -223,11 +224,16 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
qRegisterMetaType<TxProofResult>("TxProofResult"); qRegisterMetaType<TxProofResult>("TxProofResult");
qRegisterMetaType<QPair<bool, bool>>(); qRegisterMetaType<QPair<bool, bool>>();
WindowManager windowManager; EventFilter filter;
app.installEventFilter(&filter);
WindowManager windowManager(&filter);
QObject::connect(&app, &SingleApplication::instanceStarted, [&windowManager]() { QObject::connect(&app, &SingleApplication::instanceStarted, [&windowManager]() {
windowManager.raise(); windowManager.raise();
}); });
return QApplication::exec(); return QApplication::exec();
} }

19
src/utils/EventFilter.cpp Normal file
View file

@ -0,0 +1,19 @@
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-FileCopyrightText: 2020-2022 The Monero Project
#include "EventFilter.h"
#include <QKeyEvent>
#include <QDebug>
EventFilter::EventFilter(QObject *parent)
: QObject(parent)
{}
bool EventFilter::eventFilter(QObject *obj, QEvent *ev) {
if (ev->type() == QEvent::KeyPress || ev->type() == QEvent::MouseButtonRelease) {
emit userActivity();
}
return QObject::eventFilter(obj, ev);
}

25
src/utils/EventFilter.h Normal file
View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-FileCopyrightText: 2020-2022 The Monero Project
#ifndef FEATHER_EVENTFILTER_H
#define FEATHER_EVENTFILTER_H
#include <QObject>
class EventFilter : public QObject
{
Q_OBJECT
public:
explicit EventFilter(QObject *parent = nullptr);
protected:
bool eventFilter(QObject *obj, QEvent *ev);
signals:
void userActivity();
};
#endif //FEATHER_EVENTFILTER_H

View file

@ -65,6 +65,8 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::dateFormat, {QS("dateFormat"), "yyyy-MM-dd"}}, {Config::dateFormat, {QS("dateFormat"), "yyyy-MM-dd"}},
{Config::timeFormat, {QS("timeFormat"), "HH:mm"}}, {Config::timeFormat, {QS("timeFormat"), "HH:mm"}},
{Config::balanceDisplay, {QS("balanceDisplay"), Config::BalanceDisplay::spendablePlusUnconfirmed}}, {Config::balanceDisplay, {QS("balanceDisplay"), Config::BalanceDisplay::spendablePlusUnconfirmed}},
{Config::inactivityLockEnabled, {QS("inactivityLockEnabled"), false}},
{Config::inactivityLockTimeout, {QS("inactivityLockTimeout"), 10}},
{Config::multiBroadcast, {QS("multiBroadcast"), true}}, {Config::multiBroadcast, {QS("multiBroadcast"), true}},
{Config::warnOnExternalLink,{QS("warnOnExternalLink"), true}}, {Config::warnOnExternalLink,{QS("warnOnExternalLink"), true}},

View file

@ -69,6 +69,8 @@ public:
dateFormat, dateFormat,
timeFormat, timeFormat,
balanceDisplay, balanceDisplay,
inactivityLockEnabled,
inactivityLockTimeout,
multiBroadcast, multiBroadcast,
warnOnExternalLink, warnOnExternalLink,