From 5cbb24b034d9df8b5ece361d1b0411978d02fd40 Mon Sep 17 00:00:00 2001 From: "Brayan M. Salazar" Date: Mon, 29 Jul 2024 13:49:07 -0400 Subject: [PATCH] Update 1.7.0: * Added command line option to allow self restarting if Bluetooth device becomes unavailable. Older versions had to end program execution because when a Bluetooth device becomes unavailable, it won't be available for the program even when that Bluetooth device becomes available again. For more information, read: https://doc.qt.io/qt-6/qbluetoothlocaldevice.html#isValid --- CMakeLists.txt | 2 +- src/listener.cpp | 66 +++++++++++++++++++++++---- src/listener.hpp | 7 ++- src/main.cpp | 39 +++++++++++++++- translations/BtScreenLocker_es_US.qm | Bin 13347 -> 15036 bytes translations/BtScreenLocker_es_US.ts | 42 ++++++++++++++++- 6 files changed, 141 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 458cfff..cc5741f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.28) project(BtScreenLocker - VERSION 1.6.5 + VERSION 1.7.0 LANGUAGES CXX DESCRIPTION "Daemon to lock your screen if trusted Bluetooth devices go away." ) diff --git a/src/listener.cpp b/src/listener.cpp index 73954d7..fd370b2 100644 --- a/src/listener.cpp +++ b/src/listener.cpp @@ -1,11 +1,13 @@ #include "listener.hpp" +#include #include #include #include #include #include #include +#include #include #include @@ -13,20 +15,28 @@ #include "devicechooser.hpp" #include "logger.hpp" -Listener::Listener(ScreenLocker &screenLocker, QObject *parent) +Listener::Listener(ScreenLocker &screenLocker, bool autorestart, int seconds, QObject *parent) : QObject{parent} , m_dbusConnection(QDBusConnection::sessionBus()) , m_screenLocker(screenLocker) + , m_restarting(false) + , m_autorestart(autorestart) + , m_seconds(seconds) , m_logger(Logger::instance()) , m_stopped(false) { - if (not m_localDevice.isValid()) { auto message = tr("There isn't a valid Bluetooth device on this machine. Can't do anything."); - QMessageBox::critical(nullptr, - tr("Error"), - message); - m_logger.log(message, Q_FUNC_INFO, Logger::FATAL); + + if (not m_autorestart) { + QMessageBox::critical(nullptr, tr("Error"), message); + m_logger.log(message, Q_FUNC_INFO, Logger::FATAL); + } + + message += tr(" Restarting in %1 seconds.").arg(QString::number(m_seconds)); + QMessageBox::warning(nullptr, tr("Warning"), message); + m_logger.log(message, Q_FUNC_INFO); + restart(); } else { m_localDevice.powerOn(); } @@ -81,6 +91,10 @@ Listener::~Listener() void Listener::start() { + if (m_restarting) { + return; + } + if (m_settings->allKeys().isEmpty()) { startDiscovery(); return; @@ -99,6 +113,10 @@ void Listener::start() void Listener::startDiscovery() { + if (m_restarting) { + return; + } + /* If constructor started it, but in main.cpp user started discovery. */ m_lookForTrustedDeviceTimer.stop(); m_logger.log(tr("Discoverying devices..."), Q_FUNC_INFO); @@ -110,18 +128,46 @@ void Listener::startDiscovery() tr("Please wait up to 30 seconds, I'll show you the devices I discover.")); } +void Listener::restart() +{ + m_restarting = true; + m_deviceDiscoverTimer.stop(); + m_lookForTrustedDeviceTimer.stop(); + + QTimer::singleShot(m_seconds * 1'000, [] () { + auto *app = QApplication::instance(); + app->quit(); + QProcess::startDetached(app->arguments()[0], app->arguments().mid(1)); + }); +} + void Listener::hostModeStateChanged(QBluetoothLocalDevice::HostMode state) { if (state == QBluetoothLocalDevice::HostPoweredOff) { m_lookForTrustedDeviceTimer.stop(); m_deviceDiscoverTimer.stop(); - auto message = tr("Bluetooth device: %1, %2 became unavailable.\n" - "Ending program execution because of this!\n\n" + + auto message = tr("Bluetooth device: %1, %2 became unavailable. ") + .arg(m_localDevice.address().toString(), m_localDevice.name()); + + if (m_autorestart) { + message += tr("Restarting in %1 seconds.").arg(QString::number(m_seconds)); + } else { + message += tr("Ending program execution because of this!\n\n" "If at some point the device: %3 becomes available again, please re-run me.") - .arg(m_localDevice.name(), m_localDevice.address().toString(), m_localDevice.name()); + .arg(m_localDevice.address().toString()); + } + QMessageBox::critical(nullptr, tr("Error"), message); m_logger.log(message, Q_FUNC_INFO, Logger::ERROR); - emit quit(); + if (not m_autorestart) { + emit quit(); + return; + } + + m_logger.log(tr("Restarting in %1 seconds to be able to use Bluetooth adapter again.") + .arg(QString::number(m_seconds))); + restart(); } } diff --git a/src/listener.hpp b/src/listener.hpp index 5013a2b..3a0e40b 100644 --- a/src/listener.hpp +++ b/src/listener.hpp @@ -29,10 +29,13 @@ class Listener : public QObject ScreenLocker &m_screenLocker; Logger &m_logger; bool m_stopped; + bool m_restarting; + bool m_autorestart; + int m_seconds; - QString deviceClassToString(const QBluetoothDeviceInfo &deviceInfo); + void restart(); public: - explicit Listener(ScreenLocker &locker, QObject *parent = nullptr); + explicit Listener(ScreenLocker &locker, bool autorestart = false, int seconds = -1, QObject *parent = nullptr); ~Listener(); void start(); void startDiscovery(); diff --git a/src/main.cpp b/src/main.cpp index 2e7231d..031b690 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -96,8 +97,25 @@ int main(int argc, char *argv[]) return enableAutostart(parser, logger, argv[0]); } + QString timeToRestart = parser.value("time-to-restart"); + bool autorestart = parser.isSet("auto-restart"); + bool ok {false}; + int seconds = timeToRestart.toInt(&ok); + + if (autorestart) { + if (not timeToRestart.isEmpty() and not ok) { + auto message = QObject::tr("%1 is not a valid value for 'seconds'.").arg(timeToRestart); + QMessageBox::critical(nullptr, QObject::tr("Error"), message); + logger.log(message, Q_FUNC_INFO, Logger::TYPE::FATAL); + } + + if (timeToRestart.isEmpty()) { + seconds = 10; /* Default to 10 seconds if user didn't provide it. */ + } + } + ScreenLocker locker; - Listener listener(locker); + Listener listener(locker, autorestart, seconds); a.connect(&listener, &Listener::lockScreen, &locker, &ScreenLocker::lockScreen); a.connect(&listener, &Listener::quit, &a, &QApplication::quit); /* When screen is locked, no scan is done. @@ -133,6 +151,12 @@ QList commandLineOptions(const char *name) { QList options; + options.append(QCommandLineOption(QStringList() << "A" << "auto-restart", + QObject::tr("Allow %1 to restart itself when your Bluetooth device " + "becomes unavailable and availabe again, e.g. when your machine suspends. " + "Default is 10 seconds.").arg(name)) + ); + options.append(QCommandLineOption(QStringList() << "a" << "autostart", QObject::tr("Register %1 to automatically start on boot.\n" "(Will always autostart with passed parameters).").arg(name)) @@ -170,6 +194,11 @@ QList commandLineOptions(const char *name) QObject::tr("Same as --discover, but for an already running %1 instance.").arg(name)) ); + options.append(QCommandLineOption(QStringList() << "t" << "time-to-restart", + QObject::tr("Time to wait before auto-restarting %1. (Only useful when combined with -A)").arg(name), + "seconds") + ); + options.append(QCommandLineOption(QStringList() << "V" << "verbose", QObject::tr("Enable verbose log.")) ); @@ -221,6 +250,14 @@ int enableAutostart(const QCommandLineParser &parser, Logger &logger, const char } QStringList args; + if (parser.isSet("auto-restart")) { + args << "-A"; + } + + if (parser.isSet("time-to-restart")) { + args << "-t" << parser.value("time-to-restart"); + } + if (parser.isSet("debug")) { args << "-D"; } diff --git a/translations/BtScreenLocker_es_US.qm b/translations/BtScreenLocker_es_US.qm index c9a71b6f5bf986e3a8201084f796893277d7a45d..2c0beb1f3e8a9d57c24bf436bc8890602bb52abd 100644 GIT binary patch delta 1931 zcmbVMZERCz6n@%uwrhLa!4~G&C~v`iP`7T~7+VZ13<(B>0RxOg1KhTE>z%i^bNAjZ ze1!gR;VZf@uSEGFLHP)3fS7_m2oltY5h553M)w2xNYI!V6Hp*PhUe`qY{Bq{AMeLG z_kGWM&U2pU?oFI9b_8r|ho?@;gnq!3H!lOz&mi#6RKRr_i*`i;|3+)AxoNGf#aO)k zBH*2d6~mhV&wdOK1c0aA*z-QE{%iQItQ~M}w%y(EG0^n2z4g#xptQxlYubKb(mVE} z7p?*h(|&69IiPXK{_imr%MsjZAMGSZ_5FgbS5^a4R~D>#juM)5y&$pO2ecFyeDcdr z^zh$~H6IKC#Xma+>w|Reh~vWPQK0fvVMrbX3YEfrudW5$Glzc-@f?4T#)u-uacMam!V9kkSs%bJd?+N@cHgwcoo4)P3uE@jR`<=dO`CCjr|v z*B#$#VDi=?+a9u8VnvC)hbjF)QQ~Slm3^@2c;_adpv`S>{|yKfx*cdV@3zKGK$XvXzWN*$@VZd`2l<~}Cu|)gd*VuA+tM;%%30y<4TmZ5PT@@5Zjtaf z#zV{{h zZ}<-kk$*zc|JUv-08aRCe@gL6+GLmiOjcP{glSSNrN%Wg;w#CnDLQ1gLpS%hBU7wk zb-AETG{-4uFK$>nvs#!gguxyLt~YlGbvBl5@?Eeq+f00j1-UduD73C0m#6~KeAnAB zfuWBQ@27YYC9ET5e&yX_YQjWwp|HSam|qB6vaShUPiEf})y%_-6kenUI3E0=7+KuA z-YSA-gTC=oJPCznk;>#}^xQ6&p4sItF*jCL&UyZE&@ny5q7oCMio~~uCb4;nA?c}< zo?v2J?9-)w^U}ofRkNO`lCkcUKQ4o;t#Z91)0J<(nkR&oE0EJ7P30(gw9~kp>xo61 zF_3EhN1K{)#Hl8x$Qn~qIulu1ROC3H4T*K9`dLkmL&b5eChR1VIhQSo_DV6`OtS;C zY=c;ugFi_;&}ne6-yq;6TF2hY2l42|&t5T3@hSn#Mj>Bxe)GZo{&f67fd?4>| z)*GDTFz+`7va_p>xR?Kk6@;6G2>*SI@qi=BtLD<-z2cbaWOFug93JUZ{uFi642Oax z9Hm-}$MtnaYR$c{8Dbo>VqH{LP; delta 642 zcmX9*Ye-XJ7=F%0&UVhu+2+hO#p5j(&TVRf6RUwg>Q6Z|tn^34qG*O11YOK>fx}Wr z8mB0Kw7g(fwB!_mh$vxT7yTiI8km>pM*RpPD`fOWKfd?jd%yR4pXYhskyE{)t16Qb zO-~NzJVsi}GN8^v{gDnB_G5SFVL%!Cj|D?0Z(jstH>#q|fawvUXH>u*K-Wz|vkQ}U zKOopyU;hALYh*jK`hX2@*eA2A0I#uQ+opiL1~wib%o4dh)dzvJT&|{c8AV7g=0fcX z;2q)~%*_zdZ~oA&4#1MaM?9HS*uu{~j{_;!5?r+rAfZkZ7&V;tR%l%a02@n%o_GV0 zX%}AGN&xqa@Mr!X@0!7WkM!kc89Xm5NZ)sZe|-_yeAlqBeH36m7@01@e9;){9ROT$ zV`$Y+zP}oW1I++eBC`H>K Ending program execution because of this! If at some point the device: %3 becomes available again, please re-run me. - El dispositivo Bluetooth: %1, %2 ya no está disponible. + El dispositivo Bluetooth: %1, %2 ya no está disponible. ¡Terminando ejecución del programa! Si en algún momento el dispositivo: %3 vuelve a estar disponible, por favor ejecútame de nuevo. @@ -300,6 +300,30 @@ Would you like to pair it? El dispositivo Bluetooth: %1 - %2 no está emparejado. Es una buena idea tenerlo emparejado. ¿Te gustaría emparejarlo? + + Restarting in %1 seconds to be able to use Bluetooth adapter again. + Reiniciando en %1 segundos para ser capaz de usar el adaptador Bluetooth de nuevo. + + + Bluetooth device: %1, %2 became unavailable. + El dispositivo Bluetooth %1, %2 dejó de estar disponible. + + + Restarting in %1 seconds. + Reiniciando en %1 segundos. + + + Ending program execution because of this! + +If at some point the device: %3 becomes available again, please re-run me. + ¡Finalizando la ejecución del programa por esto! + +Si en algún momento el dispositivo: %3 vuelve a estar disponible de nuevo, por favor ejecútame de nuevo. + + + Restarting in %1 seconds. + Reiniciando en %1 segundos. + QObject @@ -423,6 +447,22 @@ Error message: %1 No se pudo registrar el servicio D-BUS. No será posible responder a mensajes IPC. Mensaje de error: %1 + + Time to wait before auto-restarting %1. (Only useful when combined with -A) + Tiempo para esperar antes de reiniciar %1 automáticamente. (Útil únicamente cuando está combinado con -A) + + + %1 is not a valid value for 'seconds'. + %1 no es un valor válido para 'segundos'. + + + Error + Error + + + Allow %1 to restart itself when your Bluetooth device becomes unavailable and availabe again, e.g. when your machine suspends. Default is 10 seconds. + Permitir que %1 se reinicie cuando tu dispositivo Bluetooth se vuelve inaccesible and vuelve a estar disponible de nuevo, por ejemplo, cuando tu computadora se suspende. 10 segundos por defecto. + ScreenLocker