From 0dbac78e17c36b22c3a6f4976c287c009093b2dd Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 5 Dec 2023 03:13:37 +0800 Subject: [PATCH] Revise legal notice For GUI and non-daemon console, the legal notice won't ask for user acceptance anymore and only provide an OK button (or Enter key in console) from now on. For daemon mode, qbt will print the legal notice and continue to run. It will also notify user to use command line option `--confirm-legal-notice` to suppress the message. The message will be printed on every start up unless user specify the command line option once. PR #20080. --- src/app/CMakeLists.txt | 2 + src/app/application.cpp | 15 +++--- src/app/cmdoptions.cpp | 13 ++++- src/app/cmdoptions.h | 3 +- src/app/legalnotice.cpp | 77 ++++++++++++++++++++++++++++ src/app/legalnotice.h | 31 +++++++++++ src/app/main.cpp | 99 ++++++++++++------------------------ src/base/preferences.cpp | 13 ----- src/base/preferences.h | 2 - src/base/settingsstorage.cpp | 6 +++ src/base/settingsstorage.h | 1 + 11 files changed, 169 insertions(+), 93 deletions(-) create mode 100644 src/app/legalnotice.cpp create mode 100644 src/app/legalnotice.h diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index e4d7747d7..b5174aa45 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -38,6 +38,7 @@ target_sources(qbt_app PRIVATE applicationinstancemanager.h cmdoptions.h filelogger.h + legalnotice.h qtlocalpeer/qtlocalpeer.h signalhandler.h upgrade.h @@ -47,6 +48,7 @@ target_sources(qbt_app PRIVATE applicationinstancemanager.cpp cmdoptions.cpp filelogger.cpp + legalnotice.cpp main.cpp qtlocalpeer/qtlocalpeer.cpp signalhandler.cpp diff --git a/src/app/application.cpp b/src/app/application.cpp index c052d0bd5..c7cb2a02c 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -57,7 +57,6 @@ #include #ifdef Q_OS_WIN #include -#include #endif // Q_OS_WIN #ifdef Q_OS_MACOS #include @@ -92,7 +91,6 @@ #include "upgrade.h" #ifndef DISABLE_GUI -#include "gui/guiaddtorrentmanager.h" #include "gui/desktopintegration.h" #include "gui/mainwindow.h" #include "gui/shutdownconfirmdialog.h" @@ -271,17 +269,18 @@ Application::Application(int &argc, char **argv) SettingsStorage::initInstance(); Preferences::initInstance(); - const bool firstTimeUser = !Preferences::instance()->getAcceptedLegal(); - if (!firstTimeUser) + const bool firstTimeUser = SettingsStorage::instance()->isEmpty(); + if (firstTimeUser) + { + setCurrentMigrationVersion(); + handleChangedDefaults(DefaultPreferencesMode::Current); + } + else { if (!upgrade()) throw RuntimeError(u"Failed migration of old settings"_s); // Not translatable. Translation isn't configured yet. handleChangedDefaults(DefaultPreferencesMode::Legacy); } - else - { - handleChangedDefaults(DefaultPreferencesMode::Current); - } initializeTranslation(); diff --git a/src/app/cmdoptions.cpp b/src/app/cmdoptions.cpp index 5b1d957b6..21820c85e 100644 --- a/src/app/cmdoptions.cpp +++ b/src/app/cmdoptions.cpp @@ -302,7 +302,10 @@ namespace }; constexpr const BoolOption SHOW_HELP_OPTION {"help", 'h'}; +#if !defined(Q_OS_WIN) || defined(DISABLE_GUI) constexpr const BoolOption SHOW_VERSION_OPTION {"version", 'v'}; +#endif + constexpr const BoolOption CONFIRM_LEGAL_NOTICE {"confirm-legal-notice"}; #if defined(DISABLE_GUI) && !defined(Q_OS_WIN) constexpr const BoolOption DAEMON_OPTION {"daemon", 'd'}; #else @@ -323,7 +326,8 @@ namespace } QBtCommandLineParameters::QBtCommandLineParameters(const QProcessEnvironment &env) - : relativeFastresumePaths(RELATIVE_FASTRESUME.value(env)) + : confirmLegalNotice(CONFIRM_LEGAL_NOTICE.value(env)) + , relativeFastresumePaths(RELATIVE_FASTRESUME.value(env)) #ifndef DISABLE_GUI , noSplash(NO_SPLASH_OPTION.value(env)) #elif !defined(Q_OS_WIN) @@ -365,6 +369,10 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args) result.showVersion = true; } #endif + else if (arg == CONFIRM_LEGAL_NOTICE) + { + result.confirmLegalNotice = true; + } else if (arg == WEBUI_PORT_OPTION) { result.webUIPort = WEBUI_PORT_OPTION.value(arg); @@ -484,10 +492,11 @@ QString makeUsage(const QString &prgName) + indentation + prgName + u' ' + QCoreApplication::translate("CMD Options", "[options] [( | )...]") + u'\n' + QCoreApplication::translate("CMD Options", "Options:") + u'\n' + + SHOW_HELP_OPTION.usage() + wrapText(QCoreApplication::translate("CMD Options", "Display this help message and exit")) + u'\n' #if !defined(Q_OS_WIN) || defined(DISABLE_GUI) + SHOW_VERSION_OPTION.usage() + wrapText(QCoreApplication::translate("CMD Options", "Display program version and exit")) + u'\n' #endif - + SHOW_HELP_OPTION.usage() + wrapText(QCoreApplication::translate("CMD Options", "Display this help message and exit")) + u'\n' + + CONFIRM_LEGAL_NOTICE.usage() + wrapText(QCoreApplication::translate("CMD Options", "Confirm the legal notice")) + u'\n' + WEBUI_PORT_OPTION.usage(QCoreApplication::translate("CMD Options", "port")) + wrapText(QCoreApplication::translate("CMD Options", "Change the WebUI port")) + u'\n' diff --git a/src/app/cmdoptions.h b/src/app/cmdoptions.h index 1c133c413..c4b42053f 100644 --- a/src/app/cmdoptions.h +++ b/src/app/cmdoptions.h @@ -44,10 +44,11 @@ class QProcessEnvironment; struct QBtCommandLineParameters { bool showHelp = false; - bool relativeFastresumePaths = false; #if !defined(Q_OS_WIN) || defined(DISABLE_GUI) bool showVersion = false; #endif + bool confirmLegalNotice = false; + bool relativeFastresumePaths = false; #ifndef DISABLE_GUI bool noSplash = false; #elif !defined(Q_OS_WIN) diff --git a/src/app/legalnotice.cpp b/src/app/legalnotice.cpp new file mode 100644 index 000000000..af46ee9e5 --- /dev/null +++ b/src/app/legalnotice.cpp @@ -0,0 +1,77 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2023 Mike Tzou (Chocobo1) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "legalnotice.h" + +#ifdef DISABLE_GUI +#include +#endif // DISABLE_GUI + +#include +#include + +#ifndef DISABLE_GUI +#include +#endif // DISABLE_GUI + +#include "base/global.h" + +#ifndef DISABLE_GUI +#include "gui/utils.h" +#endif // DISABLE_GUI + +void showLegalNotice(const bool isInteractive) +{ + const QString noticeTitle = QCoreApplication::translate("LegalNotice", "Legal Notice"); + const QString noticeBody = QCoreApplication::translate("LegalNotice", "qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility."); + const QString noticeEnd = QCoreApplication::translate("LegalNotice", "No further notices will be issued."); + + if (!isInteractive) + { + const QString legalNotice = u"\n*** %1 ***\n"_s.arg(noticeTitle) + + noticeBody + u"\n\n" + + QCoreApplication::translate("LegalNotice", "If you have read the legal notice, you can use command line option `--confirm-legal-notice` to suppress this message."); + printf("%s\n\n", qUtf8Printable(legalNotice)); + return; + } + +#ifdef DISABLE_GUI + const QString legalNotice = u"\n*** %1 ***\n"_s.arg(noticeTitle) + + noticeBody + u"\n\n" + + noticeEnd + u"\n\n" + + QCoreApplication::translate("LegalNotice", "Press 'Enter' key to continue..."); + printf("%s", qUtf8Printable(legalNotice)); + getchar(); +#else // DISABLE_GUI + const QString messageBody = noticeBody + u"\n\n" + noticeEnd; + QMessageBox msgBox {QMessageBox::NoIcon, noticeTitle, messageBody, QMessageBox::Ok}; + msgBox.show(); // Need to be shown first or moveToCenter does not work + msgBox.move(Utils::Gui::screenCenter(&msgBox)); + msgBox.exec(); +#endif // DISABLE_GUI +} diff --git a/src/app/legalnotice.h b/src/app/legalnotice.h new file mode 100644 index 000000000..62d47cd4f --- /dev/null +++ b/src/app/legalnotice.h @@ -0,0 +1,31 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2023 Mike Tzou (Chocobo1) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#pragma once + +void showLegalNotice(bool isInteractive); diff --git a/src/app/main.cpp b/src/app/main.cpp index 5d2c7d042..066a5c2da 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #include #include @@ -76,11 +75,12 @@ Q_IMPORT_PLUGIN(QICOPlugin) #include "base/logger.h" #include "base/preferences.h" #include "base/profile.h" +#include "base/settingvalue.h" #include "base/version.h" #include "application.h" #include "cmdoptions.h" +#include "legalnotice.h" #include "signalhandler.h" -#include "upgrade.h" #ifndef DISABLE_GUI #include "gui/utils.h" @@ -89,7 +89,6 @@ Q_IMPORT_PLUGIN(QICOPlugin) using namespace std::chrono_literals; void displayVersion(); -bool userAgreesWithLegalNotice(); void displayBadArgMessage(const QString &message); void displayErrorMessage(const QString &message); @@ -168,28 +167,6 @@ int main(int argc, char *argv[]) .arg(u"-h (or --help)"_s)); } - const bool firstTimeUser = !Preferences::instance()->getAcceptedLegal(); - if (firstTimeUser) - { -#ifndef DISABLE_GUI - if (!userAgreesWithLegalNotice()) - return EXIT_SUCCESS; -#elif defined(Q_OS_WIN) - if (_isatty(_fileno(stdin)) - && _isatty(_fileno(stdout)) - && !userAgreesWithLegalNotice()) - return EXIT_SUCCESS; -#else - if (!params.shouldDaemonize - && isatty(fileno(stdin)) - && isatty(fileno(stdout)) - && !userAgreesWithLegalNotice()) - return EXIT_SUCCESS; -#endif - - setCurrentMigrationVersion(); - } - // Check if qBittorrent is already running if (app->hasAnotherInstance()) { @@ -197,7 +174,14 @@ int main(int argc, char *argv[]) if (params.shouldDaemonize) { throw CommandLineParameterError(QCoreApplication::translate("Main", "You cannot use %1: qBittorrent is already running.") - .arg(u"-d (or --daemon)"_s)); + .arg(u"-d (or --daemon)"_s)); + } + + // print friendly message if there are no other command line args + if (argc == 1) + { + const QString message = QCoreApplication::translate("Main", "Another qBittorrent instance is already running."); + printf("%s\n", qUtf8Printable(message)); } #endif @@ -207,6 +191,26 @@ int main(int argc, char *argv[]) return EXIT_SUCCESS; } + CachedSettingValue legalNoticeShown {u"LegalNotice/Accepted"_s, false}; + if (params.confirmLegalNotice) + legalNoticeShown = true; + + if (!legalNoticeShown) + { +#ifndef DISABLE_GUI + const bool isInteractive = true; +#elif defined(Q_OS_WIN) + const bool isInteractive = (_isatty(_fileno(stdin)) != 0) && (_isatty(_fileno(stdout)) != 0); +#else + // when run in daemon mode user can only dismiss the notice with command line option + const bool isInteractive = !params.shouldDaemonize + && ((isatty(fileno(stdin)) != 0) && (isatty(fileno(stdout)) != 0)); +#endif + showLegalNotice(isInteractive); + if (isInteractive) + legalNoticeShown = true; + } + #ifdef Q_OS_MACOS // Since Apple made difficult for users to set PATH, we set here for convenience. // Users are supposed to install Homebrew Python for search function. @@ -294,13 +298,13 @@ void displayBadArgMessage(const QString &message) { const QString help = QCoreApplication::translate("Main", "Run application with -h option to read about command line parameters."); #if defined(Q_OS_WIN) && !defined(DISABLE_GUI) - QMessageBox msgBox(QMessageBox::Critical, QCoreApplication::translate("Main", "Bad command line"), + QMessageBox msgBox(QMessageBox::Critical, QCoreApplication::translate("Main", "Bad command line options"), (message + u'\n' + help), QMessageBox::Ok); msgBox.show(); // Need to be shown or to moveToCenter does not work msgBox.move(Utils::Gui::screenCenter(&msgBox)); msgBox.exec(); #else - const QString errMsg = QCoreApplication::translate("Main", "Bad command line: ") + u'\n' + const QString errMsg = QCoreApplication::translate("Main", "Bad command line options:") + u'\n' + message + u'\n' + help + u'\n'; fprintf(stderr, "%s", qUtf8Printable(errMsg)); @@ -331,45 +335,6 @@ void displayErrorMessage(const QString &message) #endif } -bool userAgreesWithLegalNotice() -{ - Preferences *const pref = Preferences::instance(); - Q_ASSERT(!pref->getAcceptedLegal()); - -#ifdef DISABLE_GUI - const QString eula = u"\n*** %1 ***\n"_s.arg(QCoreApplication::translate("Main", "Legal Notice")) - + QCoreApplication::translate("Main", "qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.") + u"\n\n" - + QCoreApplication::translate("Main", "No further notices will be issued.") + u"\n\n" - + QCoreApplication::translate("Main", "Press %1 key to accept and continue...").arg(u"'y'"_s) + u'\n'; - printf("%s", qUtf8Printable(eula)); - - const char ret = getchar(); // Read pressed key - if ((ret == 'y') || (ret == 'Y')) - { - // Save the answer - pref->setAcceptedLegal(true); - return true; - } -#else - QMessageBox msgBox; - msgBox.setText(QCoreApplication::translate("Main", "qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued.")); - msgBox.setWindowTitle(QCoreApplication::translate("Main", "Legal notice")); - msgBox.addButton(QCoreApplication::translate("Main", "Cancel"), QMessageBox::RejectRole); - const QAbstractButton *agreeButton = msgBox.addButton(QCoreApplication::translate("Main", "I Agree"), QMessageBox::AcceptRole); - msgBox.show(); // Need to be shown or to moveToCenter does not work - msgBox.move(Utils::Gui::screenCenter(&msgBox)); - msgBox.exec(); - if (msgBox.clickedButton() == agreeButton) - { - // Save the answer - pref->setAcceptedLegal(true); - return true; - } -#endif // DISABLE_GUI - - return false; -} - #ifdef Q_OS_UNIX void adjustFileDescriptorLimit() { diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index 8dd1b4f87..32ddcc0ab 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -1480,19 +1480,6 @@ void Preferences::setDNSLastIP(const QString &ip) setValue(u"DNSUpdater/lastIP"_s, ip); } -bool Preferences::getAcceptedLegal() const -{ - return value(u"LegalNotice/Accepted"_s, false); -} - -void Preferences::setAcceptedLegal(const bool accepted) -{ - if (accepted == getAcceptedLegal()) - return; - - setValue(u"LegalNotice/Accepted"_s, accepted); -} - QByteArray Preferences::getMainGeometry() const { return value(u"MainWindow/geometry"_s); diff --git a/src/base/preferences.h b/src/base/preferences.h index f7af048a8..8d78a6404 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -340,8 +340,6 @@ public: void setDNSLastUpd(const QDateTime &date); QString getDNSLastIP() const; void setDNSLastIP(const QString &ip); - bool getAcceptedLegal() const; - void setAcceptedLegal(bool accepted); QByteArray getMainGeometry() const; void setMainGeometry(const QByteArray &geometry); bool isFiltersSidebarVisible() const; diff --git a/src/base/settingsstorage.cpp b/src/base/settingsstorage.cpp index ed8f03b0d..9f19f0891 100644 --- a/src/base/settingsstorage.cpp +++ b/src/base/settingsstorage.cpp @@ -224,3 +224,9 @@ bool SettingsStorage::hasKey(const QString &key) const const QReadLocker locker {&m_lock}; return m_data.contains(key); } + +bool SettingsStorage::isEmpty() const +{ + const QReadLocker locker {&m_lock}; + return m_data.isEmpty(); +} diff --git a/src/base/settingsstorage.h b/src/base/settingsstorage.h index 7abbdae46..9163d605a 100644 --- a/src/base/settingsstorage.h +++ b/src/base/settingsstorage.h @@ -109,6 +109,7 @@ public: void removeValue(const QString &key); bool hasKey(const QString &key) const; + bool isEmpty() const; public slots: bool save();