qBittorrent
Application Class Referencefinal

#include <application.h>

Inheritance diagram for Application:
Collaboration diagram for Application:

Public Member Functions

 Application (int &argc, char **argv)
 
 ~Application () override
 
bool isRunning ()
 
int exec (const QStringList &params)
 
bool sendParams (const QStringList &params)
 
QPointer< MainWindowmainWindow ()
 
const QBtCommandLineParameterscommandLineArgs () const
 
bool isFileLoggerEnabled () const
 
void setFileLoggerEnabled (bool value)
 
QString fileLoggerPath () const
 
void setFileLoggerPath (const QString &path)
 
bool isFileLoggerBackup () const
 
void setFileLoggerBackup (bool value)
 
bool isFileLoggerDeleteOld () const
 
void setFileLoggerDeleteOld (bool value)
 
int fileLoggerMaxSize () const
 
void setFileLoggerMaxSize (int bytes)
 
int fileLoggerAge () const
 
void setFileLoggerAge (int value)
 
int fileLoggerAgeType () const
 
void setFileLoggerAgeType (int value)
 

Private Slots

void processMessage (const QString &message)
 
void torrentFinished (BitTorrent::Torrent *const torrent)
 
void allTorrentsFinished ()
 
void cleanup ()
 

Private Member Functions

void initializeTranslation ()
 
void processParams (const QStringList &params)
 
void runExternalProgram (const BitTorrent::Torrent *torrent) const
 
void sendNotificationEmail (const BitTorrent::Torrent *torrent)
 

Private Attributes

ApplicationInstanceManagerm_instanceManager = nullptr
 
bool m_running
 
ShutdownDialogAction m_shutdownAct
 
QBtCommandLineParameters m_commandLineArgs
 
QPointer< MainWindowm_window
 
WebUIm_webui = nullptr
 
QPointer< FileLoggerm_fileLogger
 
QTranslator m_qtTranslator
 
QTranslator m_translator
 
QStringList m_paramsQueue
 
SettingValue< bool > m_storeFileLoggerEnabled
 
SettingValue< bool > m_storeFileLoggerBackup
 
SettingValue< bool > m_storeFileLoggerDeleteOld
 
SettingValue< int > m_storeFileLoggerMaxSize
 
SettingValue< int > m_storeFileLoggerAge
 
SettingValue< int > m_storeFileLoggerAgeType
 
SettingValue< QString > m_storeFileLoggerPath
 

Detailed Description

Definition at line 72 of file application.h.

Constructor & Destructor Documentation

◆ Application()

Application::Application ( int &  argc,
char **  argv 
)

Definition at line 119 of file application.cpp.

120  : BaseApplication(argc, argv)
121  , m_running(false)
123  , m_commandLineArgs(parseCommandLine(this->arguments()))
131 {
132  qRegisterMetaType<Log::Msg>("Log::Msg");
133  qRegisterMetaType<Log::Peer>("Log::Peer");
134 
135  setApplicationName("qBittorrent");
136  setOrganizationDomain("qbittorrent.org");
137 #if !defined(DISABLE_GUI)
138  setDesktopFileName("org.qbittorrent.qBittorrent");
139 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
140  setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
141 #endif
142  setQuitOnLastWindowClosed(false);
143  QPixmapCache::setCacheLimit(PIXMAP_CACHE_SIZE);
144 #endif
145 
146  const bool portableModeEnabled = m_commandLineArgs.profileDir.isEmpty()
147  && QDir(QCoreApplication::applicationDirPath()).exists(DEFAULT_PORTABLE_MODE_PROFILE_DIR);
148 
149  const QString profileDir = portableModeEnabled
150  ? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
153  (m_commandLineArgs.relativeFastresumePaths || portableModeEnabled));
154 
156 
160 
162 
163  if (m_commandLineArgs.webUiPort > 0) // it will be -1 when user did not set any value
165 
166  connect(this, &QCoreApplication::aboutToQuit, this, &Application::cleanup);
168 #if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
169  connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
170 #endif
171 
172  if (isFileLoggerEnabled())
174 
175  Logger::instance()->addMessage(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QBT_VERSION));
176  if (portableModeEnabled)
177  {
178  Logger::instance()->addMessage(tr("Running in portable mode. Auto detected profile folder at: %1").arg(profileDir));
180  Logger::instance()->addMessage(tr("Redundant command line flag detected: \"%1\". Portable mode implies relative fastresume.").arg("--relative-fastresume"), Log::WARNING); // to avoid translating the `--relative-fastresume` string
181  }
182  else
183  {
184  Logger::instance()->addMessage(tr("Using config directory: %1").arg(Profile::instance()->location(SpecialFolder::Config)));
185  }
186 }
#define FILELOGGER_SETTINGS_KEY(name)
QApplication BaseApplication
Definition: application.h:38
int fileLoggerAge() const
QPointer< FileLogger > m_fileLogger
Definition: application.h:143
SettingValue< bool > m_storeFileLoggerDeleteOld
Definition: application.h:151
int fileLoggerAgeType() const
bool isFileLoggerEnabled() const
QBtCommandLineParameters m_commandLineArgs
Definition: application.h:132
bool isFileLoggerDeleteOld() const
SettingValue< QString > m_storeFileLoggerPath
Definition: application.h:155
SettingValue< bool > m_storeFileLoggerEnabled
Definition: application.h:149
bool isFileLoggerBackup() const
SettingValue< bool > m_storeFileLoggerBackup
Definition: application.h:150
SettingValue< int > m_storeFileLoggerAge
Definition: application.h:153
SettingValue< int > m_storeFileLoggerMaxSize
Definition: application.h:152
bool m_running
Definition: application.h:130
QString fileLoggerPath() const
void processMessage(const QString &message)
SettingValue< int > m_storeFileLoggerAgeType
Definition: application.h:154
ApplicationInstanceManager * m_instanceManager
Definition: application.h:129
void cleanup()
void initializeTranslation()
int fileLoggerMaxSize() const
ShutdownDialogAction m_shutdownAct
Definition: application.h:131
void messageReceived(const QString &message)
static void initInstance()
Definition: logger.cpp:61
void addMessage(const QString &message, const Log::MsgType &type=Log::NORMAL)
Definition: logger.cpp:73
static Logger * instance()
Definition: logger.cpp:56
static Preferences * instance()
static void initInstance()
void setWebUiPort(quint16 port)
QString location(SpecialFolder folder) const
Definition: profile.cpp:72
static void initInstance(const QString &rootProfilePath, const QString &configurationName, bool convertPathsToProfileRelative)
Definition: profile.cpp:53
static const Profile * instance()
Definition: profile.cpp:67
static void initInstance()
QBtCommandLineParameters parseCommandLine(const QStringList &args)
Definition: cmdoptions.cpp:399
@ WARNING
Definition: logger.h:47

References Logger::addMessage(), cleanup(), Config, QBtCommandLineParameters::configurationName, anonymous_namespace{application.cpp}::DEFAULT_PORTABLE_MODE_PROFILE_DIR, Exit, fileLoggerAge(), fileLoggerAgeType(), fileLoggerMaxSize(), fileLoggerPath(), initializeTranslation(), Logger::initInstance(), Preferences::initInstance(), SettingsStorage::initInstance(), Profile::initInstance(), Logger::instance(), Preferences::instance(), Profile::instance(), isFileLoggerBackup(), isFileLoggerDeleteOld(), isFileLoggerEnabled(), Profile::location(), m_commandLineArgs, m_fileLogger, m_instanceManager, ApplicationInstanceManager::messageReceived(), anonymous_namespace{application.cpp}::PIXMAP_CACHE_SIZE, processMessage(), QBtCommandLineParameters::profileDir, QBtCommandLineParameters::relativeFastresumePaths, Preferences::setWebUiPort(), Log::WARNING, and QBtCommandLineParameters::webUiPort.

Here is the call graph for this function:

◆ ~Application()

Application::~Application ( )
override

Definition at line 188 of file application.cpp.

189 {
190  // we still need to call cleanup()
191  // in case the App failed to start
192  cleanup();
193 }

References cleanup().

Here is the call graph for this function:

Member Function Documentation

◆ allTorrentsFinished

void Application::allTorrentsFinished ( )
privateslot

Definition at line 472 of file application.cpp.

473 {
474  Preferences *const pref = Preferences::instance();
475  bool isExit = pref->shutdownqBTWhenDownloadsComplete();
476  bool isShutdown = pref->shutdownWhenDownloadsComplete();
477  bool isSuspend = pref->suspendWhenDownloadsComplete();
478  bool isHibernate = pref->hibernateWhenDownloadsComplete();
479 
480  bool haveAction = isExit || isShutdown || isSuspend || isHibernate;
481  if (!haveAction) return;
482 
484  if (isSuspend)
486  else if (isHibernate)
488  else if (isShutdown)
490 
491 #ifndef DISABLE_GUI
492  // ask confirm
494  {
495  // do nothing & skip confirm
496  }
497  else
498  {
500  }
501 #endif // DISABLE_GUI
502 
503  // Actually shut down
505  {
506  qDebug("Preparing for auto-shutdown because all downloads are complete!");
507  // Disabling it for next time
509  pref->setSuspendWhenDownloadsComplete(false);
511  // Make sure preferences are synced before exiting
513  }
514 
515  qDebug("Exiting the application");
516  exit();
517 }
QPointer< MainWindow > m_window
Definition: application.h:135
bool shutdownqBTWhenDownloadsComplete() const
bool shutdownWhenDownloadsComplete() const
void setSuspendWhenDownloadsComplete(bool suspend)
bool suspendWhenDownloadsComplete() const
bool dontConfirmAutoExit() const
void setShutdownWhenDownloadsComplete(bool shutdown)
void setHibernateWhenDownloadsComplete(bool hibernate)
bool hibernateWhenDownloadsComplete() const
static bool askForConfirmation(QWidget *parent, const ShutdownDialogAction &action)
action
Definition: tstool.py:143
ShutdownDialogAction
Definition: types.h:36

References tstool::action, ShutdownConfirmDialog::askForConfirmation(), Preferences::dontConfirmAutoExit(), Exit, Hibernate, Preferences::hibernateWhenDownloadsComplete(), Preferences::instance(), m_shutdownAct, m_window, Preferences::setHibernateWhenDownloadsComplete(), Preferences::setShutdownWhenDownloadsComplete(), Preferences::setSuspendWhenDownloadsComplete(), Shutdown, Preferences::shutdownqBTWhenDownloadsComplete(), Preferences::shutdownWhenDownloadsComplete(), Suspend, and Preferences::suspendWhenDownloadsComplete().

Referenced by exec().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup

void Application::cleanup ( )
privateslot

Definition at line 774 of file application.cpp.

775 {
776  // cleanup() can be called multiple times during shutdown. We only need it once.
777  static QAtomicInt alreadyDone;
778  if (!alreadyDone.testAndSetAcquire(0, 1))
779  return;
780 
781 #ifndef DISABLE_GUI
782  if (m_window)
783  {
784  // Hide the window and don't leave it on screen as
785  // unresponsive. Also for Windows take the WinId
786  // after it's hidden, because hide() may cause a
787  // WinId change.
788  m_window->hide();
789 
790 #ifdef Q_OS_WIN
791  ::ShutdownBlockReasonCreate(reinterpret_cast<HWND>(m_window->effectiveWinId())
792  , tr("Saving torrent progress...").toStdWString().c_str());
793 #endif // Q_OS_WIN
794 
795  // Do manual cleanup in MainWindow to force widgets
796  // to save their Preferences, stop all timers and
797  // delete as many widgets as possible to leave only
798  // a 'shell' MainWindow.
799  // We need a valid window handle for Windows Vista+
800  // otherwise the system shutdown will continue even
801  // though we created a ShutdownBlockReason
802  m_window->cleanup();
803  }
804 #endif // DISABLE_GUI
805 
806 #ifndef DISABLE_WEBUI
807  delete m_webui;
808 #endif
809 
811  delete RSS::Session::instance();
812 
820  delete m_fileLogger;
825 
826 #ifndef DISABLE_GUI
827  if (m_window)
828  {
829 #ifdef Q_OS_WIN
830  ::ShutdownBlockReasonDestroy(reinterpret_cast<HWND>(m_window->effectiveWinId()));
831 #endif // Q_OS_WIN
832  delete m_window;
834  }
835 #endif // DISABLE_GUI
836 
838 
840  {
841  qDebug() << "Sending computer shutdown/suspend/hibernate signal...";
843  }
844 }
WebUI * m_webui
Definition: application.h:139
static void freeInstance()
Definition: session.cpp:991
static void freeInstance()
static void freeInstance()
Definition: logger.cpp:67
static void freeInstance()
static void freeInstance()
static void freeInstance()
static void freeInstance()
Definition: profile.cpp:61
static AutoDownloader * instance()
static Session * instance()
static void freeInstance()
static void freeInstance()
void removeDirRecursive(const QString &path)
Definition: fs.cpp:187
QString tempPath()
Definition: fs.cpp:314
void shutdownComputer(const ShutdownDialogAction &action)
Definition: misc.cpp:110

References Exit, BitTorrent::Session::freeInstance(), IconProvider::freeInstance(), Logger::freeInstance(), Net::DownloadManager::freeInstance(), Net::GeoIPManager::freeInstance(), Net::ProxyConfigurationManager::freeInstance(), Preferences::freeInstance(), Profile::freeInstance(), SearchPluginManager::freeInstance(), SettingsStorage::freeInstance(), TorrentFilesWatcher::freeInstance(), UIThemeManager::freeInstance(), RSS::AutoDownloader::instance(), RSS::Session::instance(), m_fileLogger, m_shutdownAct, m_webui, m_window, Utils::Fs::removeDirRecursive(), Utils::Misc::shutdownComputer(), and Utils::Fs::tempPath().

Referenced by Application(), and ~Application().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ commandLineArgs()

const QBtCommandLineParameters & Application::commandLineArgs ( ) const

Definition at line 202 of file application.cpp.

203 {
204  return m_commandLineArgs;
205 }

References m_commandLineArgs.

◆ exec()

int Application::exec ( const QStringList &  params)

Definition at line 603 of file application.cpp.

604 {
608 
609  try
610  {
614 
617 
618 #ifndef DISABLE_WEBUI
619  m_webui = new WebUI;
620 #ifdef DISABLE_GUI
621  if (m_webui->isErrored())
622  return 1;
623  connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
624 #endif // DISABLE_GUI
625 #endif // DISABLE_WEBUI
626 
627  new RSS::Session; // create RSS::Session singleton
628  new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
629  }
630  catch (const RuntimeError &err)
631  {
632 #ifdef DISABLE_GUI
633  fprintf(stderr, "%s", qPrintable(err.message()));
634 #else
635  QMessageBox msgBox;
636  msgBox.setIcon(QMessageBox::Critical);
637  msgBox.setText(tr("Application failed to start."));
638  msgBox.setInformativeText(err.message());
639  msgBox.show(); // Need to be shown or to moveToCenter does not work
640  msgBox.move(Utils::Gui::screenCenter(&msgBox));
641  msgBox.exec();
642 #endif
643  return 1;
644  }
645 
646 #ifdef DISABLE_GUI
647 #ifndef DISABLE_WEBUI
648  const Preferences *pref = Preferences::instance();
649 
650  const auto scheme = QString::fromLatin1(pref->isWebUiHttpsEnabled() ? "https" : "http");
651  const auto url = QString::fromLatin1("%1://localhost:%2\n").arg(scheme, QString::number(pref->getWebUiPort()));
652  const QString mesg = QString::fromLatin1("\n******** %1 ********\n").arg(tr("Information"))
653  + tr("To control qBittorrent, access the WebUI at: %1").arg(url);
654  printf("%s\n", qUtf8Printable(mesg));
655 
656  if (pref->getWebUIPassword() == "ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==")
657  {
658  const QString warning = tr("The Web UI administrator username is: %1").arg(pref->getWebUiUsername()) + '\n'
659  + tr("The Web UI administrator password has not been changed from the default: %1").arg("adminadmin") + '\n'
660  + tr("This is a security risk, please change your password in program preferences.") + '\n';
661  printf("%s", qUtf8Printable(warning));
662  }
663 #endif // DISABLE_WEBUI
664 #else
666  m_window = new MainWindow;
667 #endif // DISABLE_GUI
668 
669  m_running = true;
670 
671  // Now UI is ready to process signals from Session
673 
674  m_paramsQueue = params + m_paramsQueue;
675  if (!m_paramsQueue.isEmpty())
676  {
678  m_paramsQueue.clear();
679  }
680  return BaseApplication::exec();
681 }
QStringList m_paramsQueue
Definition: application.h:147
void torrentFinished(BitTorrent::Torrent *const torrent)
void allTorrentsFinished()
void processParams(const QStringList &params)
static Session * instance()
Definition: session.cpp:997
static void initInstance()
Definition: session.cpp:985
void torrentFinished(Torrent *torrent)
QString message() const noexcept
Definition: exceptions.cpp:36
static void initInstance()
static void initInstance()
static void initInstance()
QByteArray getWebUIPassword() const
quint16 getWebUiPort() const
QString getWebUiUsername() const
bool isWebUiHttpsEnabled() const
static void initInstance()
Definition: webui.h:47
bool isErrored() const
Definition: webui.cpp:156
void fatalError()
QPoint screenCenter(const QWidget *w)
Definition: utils.cpp:119

References allTorrentsFinished(), BitTorrent::Session::allTorrentsFinished(), WebUI::fatalError(), Preferences::getWebUIPassword(), Preferences::getWebUiPort(), Preferences::getWebUiUsername(), BitTorrent::Session::initInstance(), IconProvider::initInstance(), Net::DownloadManager::initInstance(), Net::GeoIPManager::initInstance(), Net::ProxyConfigurationManager::initInstance(), TorrentFilesWatcher::initInstance(), UIThemeManager::initInstance(), BitTorrent::Session::instance(), Preferences::instance(), WebUI::isErrored(), Preferences::isWebUiHttpsEnabled(), m_paramsQueue, m_running, m_webui, m_window, Exception::message(), processParams(), Utils::Gui::screenCenter(), BitTorrent::Session::startUpTorrents(), torrentFinished(), and BitTorrent::Session::torrentFinished().

Here is the call graph for this function:

◆ fileLoggerAge()

int Application::fileLoggerAge ( ) const

Definition at line 271 of file application.cpp.

272 {
273  const int val = m_storeFileLoggerAge.get(1);
274  return std::min(std::max(val, 1), 365);
275 }
T get(const T &defaultValue={}) const
Definition: settingvalue.h:46

References SettingValue< T >::get(), and m_storeFileLoggerAge.

Referenced by Application(), OptionsDialog::loadOptions(), setFileLoggerDeleteOld(), and setFileLoggerEnabled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fileLoggerAgeType()

int Application::fileLoggerAgeType ( ) const

Definition at line 282 of file application.cpp.

283 {
284  const int val = m_storeFileLoggerAgeType.get(1);
285  return ((val < 0) || (val > 2)) ? 1 : val;
286 }

References SettingValue< T >::get(), and m_storeFileLoggerAgeType.

Referenced by Application(), OptionsDialog::loadOptions(), setFileLoggerDeleteOld(), and setFileLoggerEnabled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fileLoggerMaxSize()

int Application::fileLoggerMaxSize ( ) const

◆ fileLoggerPath()

QString Application::fileLoggerPath ( ) const

Definition at line 221 of file application.cpp.

222 {
224 }
QString specialFolderLocation(const SpecialFolder folder)
Definition: profile.cpp:131

References Data, SettingValue< T >::get(), anonymous_namespace{application.cpp}::LOG_FOLDER, m_storeFileLoggerPath, and specialFolderLocation().

Referenced by Application(), OptionsDialog::loadOptions(), and setFileLoggerEnabled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initializeTranslation()

void Application::initializeTranslation ( )
private

Definition at line 713 of file application.cpp.

714 {
715  Preferences *const pref = Preferences::instance();
716  // Load translation
717  const QString localeStr = pref->getLocale();
718 
719  if (m_qtTranslator.load(QLatin1String("qtbase_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) ||
720  m_qtTranslator.load(QLatin1String("qt_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
721  qDebug("Qt %s locale recognized, using translation.", qUtf8Printable(localeStr));
722  else
723  qDebug("Qt %s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
724 
725  installTranslator(&m_qtTranslator);
726 
727  if (m_translator.load(QLatin1String(":/lang/qbittorrent_") + localeStr))
728  qDebug("%s locale recognized, using translation.", qUtf8Printable(localeStr));
729  else
730  qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(localeStr));
731  installTranslator(&m_translator);
732 
733 #ifndef DISABLE_GUI
734  if (localeStr.startsWith("ar") || localeStr.startsWith("he"))
735  {
736  qDebug("Right to Left mode");
737  setLayoutDirection(Qt::RightToLeft);
738  }
739  else
740  {
741  setLayoutDirection(Qt::LeftToRight);
742  }
743 #endif
744 }
QTranslator m_translator
Definition: application.h:146
QTranslator m_qtTranslator
Definition: application.h:145
QString getLocale() const

References Preferences::getLocale(), Preferences::instance(), m_qtTranslator, and m_translator.

Referenced by Application().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isFileLoggerBackup()

bool Application::isFileLoggerBackup ( ) const

Definition at line 233 of file application.cpp.

234 {
235  return m_storeFileLoggerBackup.get(true);
236 }

References SettingValue< T >::get(), and m_storeFileLoggerBackup.

Referenced by Application(), OptionsDialog::loadOptions(), and setFileLoggerEnabled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isFileLoggerDeleteOld()

bool Application::isFileLoggerDeleteOld ( ) const

Definition at line 245 of file application.cpp.

246 {
247  return m_storeFileLoggerDeleteOld.get(true);
248 }

References SettingValue< T >::get(), and m_storeFileLoggerDeleteOld.

Referenced by Application(), OptionsDialog::loadOptions(), and setFileLoggerEnabled().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isFileLoggerEnabled()

bool Application::isFileLoggerEnabled ( ) const

Definition at line 207 of file application.cpp.

208 {
209  return m_storeFileLoggerEnabled.get(true);
210 }

References SettingValue< T >::get(), and m_storeFileLoggerEnabled.

Referenced by Application(), and OptionsDialog::loadOptions().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isRunning()

bool Application::isRunning ( )

Definition at line 683 of file application.cpp.

684 {
686 }

References ApplicationInstanceManager::isFirstInstance(), and m_instanceManager.

Here is the call graph for this function:

◆ mainWindow()

QPointer< MainWindow > Application::mainWindow ( )

Definition at line 196 of file application.cpp.

197 {
198  return m_window;
199 }

References m_window.

◆ processMessage

void Application::processMessage ( const QString &  message)
privateslot

Definition at line 293 of file application.cpp.

294 {
295  const QStringList params = message.split(PARAMS_SEPARATOR, Qt::SkipEmptyParts);
296  // If Application is not running (i.e., other
297  // components are not ready) store params
298  if (m_running)
299  processParams(params);
300  else
301  m_paramsQueue.append(params);
302 }

References m_paramsQueue, m_running, anonymous_namespace{application.cpp}::PARAMS_SEPARATOR, and processParams().

Referenced by Application().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ processParams()

void Application::processParams ( const QStringList &  params)
private

Definition at line 528 of file application.cpp.

529 {
530 #ifndef DISABLE_GUI
531  if (params.isEmpty())
532  {
533  m_window->activate(); // show UI
534  return;
535  }
536 #endif
537  BitTorrent::AddTorrentParams torrentParams;
538  std::optional<bool> skipTorrentDialog;
539 
540  for (QString param : params)
541  {
542  param = param.trimmed();
543 
544  // Process strings indicating options specified by the user.
545 
546  if (param.startsWith(QLatin1String("@savePath=")))
547  {
548  torrentParams.savePath = param.mid(10);
549  continue;
550  }
551 
552  if (param.startsWith(QLatin1String("@addPaused=")))
553  {
554  torrentParams.addPaused = (QStringView(param).mid(11).toInt() != 0);
555  continue;
556  }
557 
558  if (param == QLatin1String("@skipChecking"))
559  {
560  torrentParams.skipChecking = true;
561  continue;
562  }
563 
564  if (param.startsWith(QLatin1String("@category=")))
565  {
566  torrentParams.category = param.mid(10);
567  continue;
568  }
569 
570  if (param == QLatin1String("@sequential"))
571  {
572  torrentParams.sequential = true;
573  continue;
574  }
575 
576  if (param == QLatin1String("@firstLastPiecePriority"))
577  {
578  torrentParams.firstLastPiecePriority = true;
579  continue;
580  }
581 
582  if (param.startsWith(QLatin1String("@skipDialog=")))
583  {
584  skipTorrentDialog = (QStringView(param).mid(12).toInt() != 0);
585  continue;
586  }
587 
588 #ifndef DISABLE_GUI
589  // There are two circumstances in which we want to show the torrent
590  // dialog. One is when the application settings specify that it should
591  // be shown and skipTorrentDialog is undefined. The other is when
592  // skipTorrentDialog is false, meaning that the application setting
593  // should be overridden.
594  const bool showDialogForThisTorrent = !skipTorrentDialog.value_or(!AddNewTorrentDialog::isEnabled());
595  if (showDialogForThisTorrent)
596  AddNewTorrentDialog::show(param, torrentParams, m_window);
597  else
598 #endif
599  BitTorrent::Session::instance()->addTorrent(param, torrentParams);
600  }
601 }
static void show(const QString &source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent)
bool addTorrent(const QString &source, const AddTorrentParams &params=AddTorrentParams())
Definition: session.cpp:2007
std::optional< bool > addPaused

References BitTorrent::AddTorrentParams::addPaused, BitTorrent::Session::addTorrent(), BitTorrent::AddTorrentParams::category, BitTorrent::AddTorrentParams::firstLastPiecePriority, BitTorrent::Session::instance(), AddNewTorrentDialog::isEnabled(), m_window, BitTorrent::AddTorrentParams::savePath, BitTorrent::AddTorrentParams::sequential, AddNewTorrentDialog::show(), and BitTorrent::AddTorrentParams::skipChecking.

Referenced by exec(), and processMessage().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ runExternalProgram()

void Application::runExternalProgram ( const BitTorrent::Torrent torrent) const
private

Definition at line 304 of file application.cpp.

305 {
306 #if defined(Q_OS_WIN)
307  const auto chopPathSep = [](const QString &str) -> QString
308  {
309  if (str.endsWith('\\'))
310  return str.mid(0, (str.length() -1));
311  return str;
312  };
313 #endif
314 
315  QString program = Preferences::instance()->getAutoRunProgram().trimmed();
316 
317  for (int i = (program.length() - 2); i >= 0; --i)
318  {
319  if (program[i] != QLatin1Char('%'))
320  continue;
321 
322  const ushort specifier = program[i + 1].unicode();
323  switch (specifier)
324  {
325  case u'C':
326  program.replace(i, 2, QString::number(torrent->filesCount()));
327  break;
328  case u'D':
329 #if defined(Q_OS_WIN)
330  program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->savePath())));
331 #else
332  program.replace(i, 2, Utils::Fs::toNativePath(torrent->savePath()));
333 #endif
334  break;
335  case u'F':
336 #if defined(Q_OS_WIN)
337  program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->contentPath())));
338 #else
339  program.replace(i, 2, Utils::Fs::toNativePath(torrent->contentPath()));
340 #endif
341  break;
342  case u'G':
343  program.replace(i, 2, torrent->tags().join(QLatin1String(",")));
344  break;
345  case u'I':
346  program.replace(i, 2, (torrent->infoHash().v1().isValid() ? torrent->infoHash().v1().toString() : QLatin1String("-")));
347  break;
348  case u'J':
349  program.replace(i, 2, (torrent->infoHash().v2().isValid() ? torrent->infoHash().v2().toString() : QLatin1String("-")));
350  break;
351  case u'K':
352  program.replace(i, 2, torrent->id().toString());
353  break;
354  case u'L':
355  program.replace(i, 2, torrent->category());
356  break;
357  case u'N':
358  program.replace(i, 2, torrent->name());
359  break;
360  case u'R':
361 #if defined(Q_OS_WIN)
362  program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->rootPath())));
363 #else
364  program.replace(i, 2, Utils::Fs::toNativePath(torrent->rootPath()));
365 #endif
366  break;
367  case u'T':
368  program.replace(i, 2, torrent->currentTracker());
369  break;
370  case u'Z':
371  program.replace(i, 2, QString::number(torrent->totalSize()));
372  break;
373  default:
374  // do nothing
375  break;
376  }
377 
378  // decrement `i` to avoid unwanted replacement, example pattern: "%%N"
379  --i;
380  }
381 
382  LogMsg(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program));
383 
384 #if defined(Q_OS_WIN)
385  auto programWchar = std::make_unique<wchar_t[]>(program.length() + 1);
386  program.toWCharArray(programWchar.get());
387 
388  // Need to split arguments manually because QProcess::startDetached(QString)
389  // will strip off empty parameters.
390  // E.g. `python.exe "1" "" "3"` will become `python.exe "1" "3"`
391  int argCount = 0;
392  std::unique_ptr<LPWSTR[], decltype(&::LocalFree)> args {::CommandLineToArgvW(programWchar.get(), &argCount), ::LocalFree};
393 
394  QStringList argList;
395  for (int i = 1; i < argCount; ++i)
396  argList += QString::fromWCharArray(args[i]);
397 
398  QProcess proc;
399  proc.setProgram(QString::fromWCharArray(args[0]));
400  proc.setArguments(argList);
401  proc.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args)
402  {
403  if (Preferences::instance()->isAutoRunConsoleEnabled())
404  {
405  args->flags |= CREATE_NEW_CONSOLE;
406  args->flags &= ~(CREATE_NO_WINDOW | DETACHED_PROCESS);
407  }
408  else
409  {
410  args->flags |= CREATE_NO_WINDOW;
411  args->flags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS);
412  }
413  args->inheritHandles = false;
414  args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
415  ::CloseHandle(args->startupInfo->hStdInput);
416  ::CloseHandle(args->startupInfo->hStdOutput);
417  ::CloseHandle(args->startupInfo->hStdError);
418  args->startupInfo->hStdInput = nullptr;
419  args->startupInfo->hStdOutput = nullptr;
420  args->startupInfo->hStdError = nullptr;
421  });
422  proc.startDetached();
423 #else // Q_OS_WIN
424  // Cannot give users shell environment by default, as doing so could
425  // enable command injection via torrent name and other arguments
426  // (especially when some automated download mechanism has been setup).
427  // See: https://github.com/qbittorrent/qBittorrent/issues/10925
428  QStringList args = QProcess::splitCommand(program);
429  if (args.isEmpty())
430  return;
431 
432  const QString command = args.takeFirst();
433  QProcess::startDetached(command, args);
434 #endif
435 }
virtual int filesCount() const =0
SHA1Hash v1() const
Definition: infohash.cpp:44
SHA256Hash v2() const
Definition: infohash.cpp:53
virtual qlonglong totalSize() const =0
TorrentID id() const
Definition: torrent.cpp:54
virtual TagSet tags() const =0
virtual QString currentTracker() const =0
virtual QString category() const =0
virtual InfoHash infoHash() const =0
virtual QString savePath() const =0
virtual QString rootPath() const =0
virtual QString name() const =0
virtual QString contentPath() const =0
QString toString() const
Definition: digest32.h:85
bool isValid() const
Definition: digest32.h:58
QString join(const QString &separator) const
Definition: orderedset.h:80
QString getAutoRunProgram() const
void LogMsg(const QString &message, const Log::MsgType &type)
Definition: logger.cpp:125
QString toNativePath(const QString &path)
Definition: fs.cpp:64
args
Definition: tstool.py:153

References tstool::args, BitTorrent::Torrent::category(), BitTorrent::Torrent::contentPath(), BitTorrent::Torrent::currentTracker(), BitTorrent::AbstractFileStorage::filesCount(), Preferences::getAutoRunProgram(), BitTorrent::Torrent::id(), BitTorrent::Torrent::infoHash(), Preferences::instance(), Digest32< N >::isValid(), OrderedSet< T, Compare >::join(), LogMsg(), BitTorrent::Torrent::name(), BitTorrent::Torrent::rootPath(), BitTorrent::Torrent::savePath(), BitTorrent::Torrent::tags(), Utils::Fs::toNativePath(), Digest32< N >::toString(), BitTorrent::Torrent::totalSize(), BitTorrent::InfoHash::v1(), and BitTorrent::InfoHash::v2().

Referenced by torrentFinished().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendNotificationEmail()

void Application::sendNotificationEmail ( const BitTorrent::Torrent torrent)
private

Definition at line 437 of file application.cpp.

438 {
439  // Prepare mail content
440  const QString content = tr("Torrent name: %1").arg(torrent->name()) + '\n'
441  + tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + '\n'
442  + tr("Save path: %1").arg(torrent->savePath()) + "\n\n"
443  + tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds")
444  .arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"
445  + tr("Thank you for using qBittorrent.") + '\n';
446 
447  // Send the notification email
448  const Preferences *pref = Preferences::instance();
449  auto *smtp = new Net::Smtp(this);
450  smtp->sendMail(pref->getMailNotificationSender(),
451  pref->getMailNotificationEmail(),
452  tr("[qBittorrent] '%1' has finished downloading").arg(torrent->name()),
453  content);
454 }
virtual qlonglong activeTime() const =0
virtual qlonglong wantedSize() const =0
Definition: smtp.h:51
QString getMailNotificationEmail() const
QString getMailNotificationSender() const
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap=-1)
Definition: misc.cpp:353
QString friendlyUnit(qint64 bytes, bool isSpeed=false)
Definition: misc.cpp:261

References BitTorrent::Torrent::activeTime(), Utils::Misc::friendlyUnit(), Preferences::getMailNotificationEmail(), Preferences::getMailNotificationSender(), Preferences::instance(), BitTorrent::Torrent::name(), BitTorrent::Torrent::savePath(), Utils::Misc::userFriendlyDuration(), and BitTorrent::Torrent::wantedSize().

Referenced by torrentFinished().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendParams()

bool Application::sendParams ( const QStringList &  params)

Definition at line 519 of file application.cpp.

520 {
521  return m_instanceManager->sendMessage(params.join(PARAMS_SEPARATOR));
522 }
bool sendMessage(const QString &message, int timeout=5000)

References m_instanceManager, anonymous_namespace{application.cpp}::PARAMS_SEPARATOR, and ApplicationInstanceManager::sendMessage().

Here is the call graph for this function:

◆ setFileLoggerAge()

void Application::setFileLoggerAge ( int  value)

Definition at line 277 of file application.cpp.

278 {
279  m_storeFileLoggerAge = std::min(std::max(value, 1), 365);
280 }
T value(const QString &key, const T &defaultValue={})
Definition: preferences.cpp:64

References m_storeFileLoggerAge, and anonymous_namespace{preferences.cpp}::value().

Here is the call graph for this function:

◆ setFileLoggerAgeType()

void Application::setFileLoggerAgeType ( int  value)

Definition at line 288 of file application.cpp.

289 {
290  m_storeFileLoggerAgeType = ((value < 0) || (value > 2)) ? 1 : value;
291 }

References m_storeFileLoggerAgeType, and anonymous_namespace{preferences.cpp}::value().

Here is the call graph for this function:

◆ setFileLoggerBackup()

void Application::setFileLoggerBackup ( bool  value)

Definition at line 238 of file application.cpp.

239 {
240  if (m_fileLogger)
241  m_fileLogger->setBackup(value);
243 }

References m_fileLogger, m_storeFileLoggerBackup, and anonymous_namespace{preferences.cpp}::value().

Here is the call graph for this function:

◆ setFileLoggerDeleteOld()

void Application::setFileLoggerDeleteOld ( bool  value)

Definition at line 250 of file application.cpp.

251 {
252  if (value && m_fileLogger)
255 }

References fileLoggerAge(), fileLoggerAgeType(), m_fileLogger, m_storeFileLoggerDeleteOld, and anonymous_namespace{preferences.cpp}::value().

Here is the call graph for this function:

◆ setFileLoggerEnabled()

void Application::setFileLoggerEnabled ( bool  value)

◆ setFileLoggerMaxSize()

void Application::setFileLoggerMaxSize ( int  bytes)

Definition at line 263 of file application.cpp.

264 {
265  const int clampedValue = std::min(std::max(bytes, MIN_FILELOG_SIZE), MAX_FILELOG_SIZE);
266  if (m_fileLogger)
267  m_fileLogger->setMaxSize(clampedValue);
268  m_storeFileLoggerMaxSize = clampedValue;
269 }

References m_fileLogger, m_storeFileLoggerMaxSize, anonymous_namespace{application.cpp}::MAX_FILELOG_SIZE, and anonymous_namespace{application.cpp}::MIN_FILELOG_SIZE.

◆ setFileLoggerPath()

void Application::setFileLoggerPath ( const QString &  path)

Definition at line 226 of file application.cpp.

227 {
228  if (m_fileLogger)
229  m_fileLogger->changePath(path);
230  m_storeFileLoggerPath = path;
231 }

References m_fileLogger, and m_storeFileLoggerPath.

Referenced by OptionsDialog::saveOptions().

Here is the caller graph for this function:

◆ torrentFinished

void Application::torrentFinished ( BitTorrent::Torrent *const  torrent)
privateslot

Definition at line 456 of file application.cpp.

457 {
458  Preferences *const pref = Preferences::instance();
459 
460  // AutoRun program
461  if (pref->isAutoRunEnabled())
462  runExternalProgram(torrent);
463 
464  // Mail notification
465  if (pref->isMailNotificationEnabled())
466  {
467  Logger::instance()->addMessage(tr("Torrent: %1, sending mail notification").arg(torrent->name()));
468  sendNotificationEmail(torrent);
469  }
470 }
void sendNotificationEmail(const BitTorrent::Torrent *torrent)
void runExternalProgram(const BitTorrent::Torrent *torrent) const
bool isMailNotificationEnabled() const
bool isAutoRunEnabled() const

References Logger::addMessage(), Logger::instance(), Preferences::instance(), Preferences::isAutoRunEnabled(), Preferences::isMailNotificationEnabled(), BitTorrent::Torrent::name(), runExternalProgram(), and sendNotificationEmail().

Referenced by exec().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_commandLineArgs

QBtCommandLineParameters Application::m_commandLineArgs
private

Definition at line 132 of file application.h.

Referenced by Application(), and commandLineArgs().

◆ m_fileLogger

QPointer<FileLogger> Application::m_fileLogger
private

◆ m_instanceManager

ApplicationInstanceManager* Application::m_instanceManager = nullptr
private

Definition at line 129 of file application.h.

Referenced by Application(), isRunning(), and sendParams().

◆ m_paramsQueue

QStringList Application::m_paramsQueue
private

Definition at line 147 of file application.h.

Referenced by exec(), and processMessage().

◆ m_qtTranslator

QTranslator Application::m_qtTranslator
private

Definition at line 145 of file application.h.

Referenced by initializeTranslation().

◆ m_running

bool Application::m_running
private

Definition at line 130 of file application.h.

Referenced by exec(), and processMessage().

◆ m_shutdownAct

ShutdownDialogAction Application::m_shutdownAct
private

Definition at line 131 of file application.h.

Referenced by allTorrentsFinished(), and cleanup().

◆ m_storeFileLoggerAge

SettingValue<int> Application::m_storeFileLoggerAge
private

Definition at line 153 of file application.h.

Referenced by fileLoggerAge(), and setFileLoggerAge().

◆ m_storeFileLoggerAgeType

SettingValue<int> Application::m_storeFileLoggerAgeType
private

Definition at line 154 of file application.h.

Referenced by fileLoggerAgeType(), and setFileLoggerAgeType().

◆ m_storeFileLoggerBackup

SettingValue<bool> Application::m_storeFileLoggerBackup
private

Definition at line 150 of file application.h.

Referenced by isFileLoggerBackup(), and setFileLoggerBackup().

◆ m_storeFileLoggerDeleteOld

SettingValue<bool> Application::m_storeFileLoggerDeleteOld
private

Definition at line 151 of file application.h.

Referenced by isFileLoggerDeleteOld(), and setFileLoggerDeleteOld().

◆ m_storeFileLoggerEnabled

SettingValue<bool> Application::m_storeFileLoggerEnabled
private

Definition at line 149 of file application.h.

Referenced by isFileLoggerEnabled(), and setFileLoggerEnabled().

◆ m_storeFileLoggerMaxSize

SettingValue<int> Application::m_storeFileLoggerMaxSize
private

Definition at line 152 of file application.h.

Referenced by fileLoggerMaxSize(), and setFileLoggerMaxSize().

◆ m_storeFileLoggerPath

SettingValue<QString> Application::m_storeFileLoggerPath
private

Definition at line 155 of file application.h.

Referenced by fileLoggerPath(), and setFileLoggerPath().

◆ m_translator

QTranslator Application::m_translator
private

Definition at line 146 of file application.h.

Referenced by initializeTranslation().

◆ m_webui

WebUI* Application::m_webui = nullptr
private

Definition at line 139 of file application.h.

Referenced by cleanup(), and exec().

◆ m_window

QPointer<MainWindow> Application::m_window
private

Definition at line 135 of file application.h.

Referenced by allTorrentsFinished(), cleanup(), exec(), mainWindow(), and processParams().


The documentation for this class was generated from the following files: