1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-10-09 18:32:15 +02:00

Compare commits

...

21 Commits

Author SHA1 Message Date
sledgehammer999
c77466abb0 Bump to 4.6.0RC2 2023-08-29 03:14:00 +03:00
sledgehammer999
a9d8cf2ea9 Sync translations from Transifex and run lupdate 2023-08-29 03:13:59 +03:00
MarcDrieu
22420339a5 NSIS: Update French translation
PR #19284.
2023-08-29 03:13:57 +03:00
rusu-afanasie
9076ff8876 NSIS: Add Romanian translation
PR #19377.
2023-08-29 03:13:50 +03:00
sledgehammer999
af20233dfc Bump copyright year 2023-08-29 00:28:11 +03:00
sledgehammer999
dfd735f2dc Pull translations from Transifex 2023-08-29 00:28:03 +03:00
Vladimir Golovnev
2a04a4d077 Display error message when unrecoverable error occurred
PR #19462.
2023-08-20 15:23:31 +03:00
Vladimir Golovnev
67d340ad63 Add more precondition checks when handle async operation result
PR  #19460.
2023-08-20 15:23:31 +03:00
Vladimir Golovnev
2b69cabc2c Check returned Bundle ID for NULL
PR #19463.
2023-08-20 15:23:31 +03:00
Vladimir Golovnev
062e35e6b0 Merge pull request #19454 from glassez/v4.6
Backport changes to v4.6.x branch
2023-08-14 17:39:17 +03:00
Omar Abdul Azeez
3088b38d7e Fix overwriting feeds.json with an incomplete load of it
PR #19444.
Closes #19439.

---------

Co-authored-by: Vladimir Golovnev <glassez@yandex.ru>
2023-08-12 21:32:17 +03:00
Vladimir Golovnev
f5b5570a3b Correctly load colors from custom themes
PR #19448.
Closes #19447.
2023-08-12 21:31:46 +03:00
Chocobo1
80bb19701c Ensure file name is valid when exporting torrents
Closes #19275.
Closes #19329.
2023-08-04 12:22:48 +08:00
Chocobo1
8376707379 GHA CI: specify a category for CodeQL analysis 2023-08-04 12:22:48 +08:00
axet
483ccb39bf Inhibit suspend instead of screen idle
PR #19316.
Closes #19312.
2023-08-04 12:22:48 +08:00
Vladimir Golovnev
41e44d22ea Map selected indexes to source before modify the data
Changing the data may affect the layout of the sort/filter model, which in turn may invalidate the indexes previously obtained from selection model before we process them all. Therefore, we must map all the selected indexes to source before start processing them.

PR #19372.
Closes #19359.
2023-07-26 20:25:44 +03:00
Chocobo1
766fce82b1 Use efficient algorithm for removing entries
PR #19351.
2023-07-23 12:54:31 +08:00
Vladimir Golovnev
938adca47d Merge pull request #19334 from glassez/v4.6
Backport changes in v4.6.x branch
2023-07-19 15:03:08 +03:00
Vladimir Golovnev
5bb02cbd90 Don't initialize Properties widget size until window is shown
PR #19328.
Closes #19322.
2023-07-18 15:18:34 +03:00
Vladimir Golovnev
66777f3304 WebUI: use new format of RSS rules
PR #19326.
Fixes regression of #18824.
Closes #19323.
2023-07-18 15:18:08 +03:00
sledgehammer999
508896c4f2 Bump to 4.6.0RC1 2023-07-17 09:21:32 +03:00
139 changed files with 27627 additions and 25543 deletions

View File

@@ -117,6 +117,8 @@ jobs:
- name: Run CodeQL analysis
uses: github/codeql-action/analyze@v2
if: startsWith(matrix.libt_version, 2) && (matrix.qbt_gui == 'GUI=ON') && startsWith(matrix.qt_version, 6)
with:
category: ${{ github.base_ref || github.ref_name }}
- name: Prepare build artifacts
run: |

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for qbittorrent v4.6.0beta2.
# Generated by GNU Autoconf 2.71 for qbittorrent v4.6.0RC2.
#
# Report bugs to <bugs.qbittorrent.org>.
#
@@ -611,8 +611,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='qbittorrent'
PACKAGE_TARNAME='qbittorrent'
PACKAGE_VERSION='v4.6.0beta2'
PACKAGE_STRING='qbittorrent v4.6.0beta2'
PACKAGE_VERSION='v4.6.0RC2'
PACKAGE_STRING='qbittorrent v4.6.0RC2'
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
PACKAGE_URL='https://www.qbittorrent.org/'
@@ -1329,7 +1329,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures qbittorrent v4.6.0beta2 to adapt to many kinds of systems.
\`configure' configures qbittorrent v4.6.0RC2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1400,7 +1400,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of qbittorrent v4.6.0beta2:";;
short | recursive ) echo "Configuration of qbittorrent v4.6.0RC2:";;
esac
cat <<\_ACEOF
@@ -1533,7 +1533,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
qbittorrent configure v4.6.0beta2
qbittorrent configure v4.6.0RC2
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1648,7 +1648,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by qbittorrent $as_me v4.6.0beta2, which was
It was created by qbittorrent $as_me v4.6.0RC2, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4779,7 +4779,7 @@ fi
# Define the identity of the package.
PACKAGE='qbittorrent'
VERSION='v4.6.0beta2'
VERSION='v4.6.0RC2'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -7237,7 +7237,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by qbittorrent $as_me v4.6.0beta2, which was
This file was extended by qbittorrent $as_me v4.6.0RC2, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7297,7 +7297,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
qbittorrent config.status v4.6.0beta2
qbittorrent config.status v4.6.0RC2
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT([qbittorrent], [v4.6.0beta2], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_INIT([qbittorrent], [v4.6.0RC2], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
: ${CFLAGS=""}

2
dist/mac/Info.plist vendored
View File

@@ -67,7 +67,7 @@
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2006-2022 The qBittorrent project</string>
<string>Copyright © 2006-2023 The qBittorrent project</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>

View File

@@ -112,7 +112,7 @@ OutFile "qbittorrent_${QBT_INSTALLER_FILENAME}_setup.exe"
;Installer Version Information
VIAddVersionKey "ProductName" "qBittorrent"
VIAddVersionKey "CompanyName" "The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2022 The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2023 The qBittorrent project"
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
VIAddVersionKey "FileVersion" "${QBT_VERSION}"

View File

@@ -7,7 +7,7 @@ LangString inst_desktop ${LANG_FRENCH} "Créer un Raccourci sur le Bureau"
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_FRENCH} "Créer un Raccourci dans le Menu Démarrer"
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_FRENCH} "Démarrez qBittorrent au démarrage de Windows"
LangString inst_startup ${LANG_FRENCH} "Démarrer qBittorrent au démarrage de Windows"
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_FRENCH} "Ouvrir les fichiers .torrent avec qBittorrent"
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
@@ -15,7 +15,7 @@ LangString inst_magnet ${LANG_FRENCH} "Ouvrir les liens magnet avec qBittorrent"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_FRENCH} "Ajouter une règle au Pare-Feu de Windows"
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_FRENCH} "Désactiver la limite de taille du chemin de Windows (limitation de MAX_PATH 260 caractères, nécessite Windows 10 1607 ou plus)"
LangString inst_pathlimit ${LANG_FRENCH} "Désactiver la limite de taille des chemins de Windows (limite MAX_PATH de 260 caractères, nécessite Windows 10 1607 ou plus)"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_FRENCH} "Ajout d'une règle au Pare-Feu de Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
@@ -31,7 +31,7 @@ LangString inst_requires_64bit ${LANG_FRENCH} "Cet installateur ne fonctionne qu
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
LangString inst_requires_win7 ${LANG_FRENCH} "Cette version de qBittorrent nécessite au moins Windows 7."
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 1809."
LangString inst_requires_win10 ${LANG_FRENCH} "This installer requires at least Windows 10 1809."
LangString inst_requires_win10 ${LANG_FRENCH} "Cet installateur nécessite au moins Windows 10 1809."
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_FRENCH} "Désinstaller qBittorrent"
@@ -53,9 +53,9 @@ LangString remove_firewall ${LANG_FRENCH} "Supprimer la règle du Pare-Feu de Wi
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_FRENCH} "Suppression de la règle du Pare-Feu de Windows"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_FRENCH} "Supprimer les torrents et données cachées"
LangString remove_cache ${LANG_FRENCH} "Supprimer les torrents et données en cache"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant la désinstallation."
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Fermez l'application avant de la désinstaller."
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du .torrent. Elle est associée avec :"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"

View File

@@ -1,62 +1,62 @@
;Installer strings
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_ROMANIAN} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_ROMANIAN} "qBittorrent (obligatoriu)"
;LangString inst_desktop ${LANG_ENGLISH} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_ROMANIAN} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_ROMANIAN} "Creați o comandă rapidă pe Desktop"
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_ROMANIAN} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_ROMANIAN} "Creați o comandă rapidă în meniul Start"
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_ROMANIAN} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_ROMANIAN} "Porniți qBittorrent la pornirea Windows"
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_ROMANIAN} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_ROMANIAN} "Deschideți fișierele .torrent cu qBittorrent"
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_ROMANIAN} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_ROMANIAN} "Deschideți linkurile magnet cu qBittorrent"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_ROMANIAN} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_ROMANIAN} "Adăugați regula Windows Firewall"
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_ROMANIAN} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_ROMANIAN} "Dezactivați limita de lungime a căii Windows (260 de caractere limită MAX_PATH, necesită Windows 10 1607 sau o versiune ulterioară)"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ROMANIAN} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ROMANIAN} "Adăugarea regulii Windows Firewall"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ROMANIAN} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ROMANIAN} "qBittorrent rulează. Vă rugăm să închideți aplicația înainte de instalare."
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_ROMANIAN} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_ROMANIAN} "Versiunea actuală va fi dezinstalată. Setările utilizatorului și torrentele vor rămâne intacte."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ROMANIAN} "Uninstalling previous version."
LangString inst_unist ${LANG_ROMANIAN} "Se dezinstalează versiunea anterioară."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_ROMANIAN} "Launch qBittorrent."
LangString launch_qbt ${LANG_ROMANIAN} "Lansați qBittorrent."
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_ROMANIAN} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_ROMANIAN} "Acest program de instalare funcționează doar pe versiunile Windows pe 64 de biți."
;LangString inst_requires_win7 ${LANG_ENGLISH} "This qBittorrent version requires at least Windows 7."
LangString inst_requires_win7 ${LANG_ROMANIAN} "This qBittorrent version requires at least Windows 7."
LangString inst_requires_win7 ${LANG_ROMANIAN} "Această versiune de qBittorrent necesită cel puțin Windows 7."
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 1809."
LangString inst_requires_win10 ${LANG_ROMANIAN} "This installer requires at least Windows 10 1809."
LangString inst_requires_win10 ${LANG_ROMANIAN} "Acest program de instalare necesită cel puțin Windows 10 1809."
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_ROMANIAN} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_ROMANIAN} "Dezinstalați qBittorrent"
;------------------------------------
;Uninstaller strings
;LangString remove_files ${LANG_ENGLISH} "Remove files"
LangString remove_files ${LANG_ROMANIAN} "Remove files"
LangString remove_files ${LANG_ROMANIAN} "Eliminați fișierele"
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
LangString remove_shortcuts ${LANG_ROMANIAN} "Remove shortcuts"
LangString remove_shortcuts ${LANG_ROMANIAN} "Eliminați comenzile rapide"
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
LangString remove_associations ${LANG_ROMANIAN} "Remove file associations"
LangString remove_associations ${LANG_ROMANIAN} "Eliminați asocierile de fișiere"
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
LangString remove_registry ${LANG_ROMANIAN} "Remove registry keys"
LangString remove_registry ${LANG_ROMANIAN} "Eliminați cheile din registru"
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
LangString remove_conf ${LANG_ROMANIAN} "Remove configuration files"
LangString remove_conf ${LANG_ROMANIAN} "Eliminați fișierele de configurare"
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_ROMANIAN} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_ROMANIAN} "Eliminați regula Windows Firewall"
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_ROMANIAN} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_ROMANIAN} "Se elimină regula Windows Firewall"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_ROMANIAN} "Remove torrents and cached data"
LangString remove_cache ${LANG_ROMANIAN} "Eliminați torrentele și datele din cache"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_ROMANIAN} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_ROMANIAN} "qBittorrent rulează. Vă rugăm să închideți aplicația înainte de a o dezinstala."
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_ROMANIAN} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_ROMANIAN} "Nu se elimină asocierea .torrent. Este asociat cu:"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_ROMANIAN} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_ROMANIAN} "Nu se elimină asocierea magnet. Este asociat cu:"

View File

@@ -763,7 +763,6 @@ void Application::processParams(const QBtCommandLineParameters &params)
}
int Application::exec()
try
{
#if !defined(DISABLE_WEBUI) && defined(DISABLE_GUI)
const QString loadingStr = tr("WebUI will be started shortly after internal preparations. Please wait...");
@@ -932,21 +931,6 @@ try
return BaseApplication::exec();
}
catch (const RuntimeError &err)
{
#ifdef DISABLE_GUI
fprintf(stderr, "%s", qPrintable(err.message()));
#else
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(QCoreApplication::translate("Application", "Application failed to start."));
msgBox.setInformativeText(err.message());
msgBox.show(); // Need to be shown or to moveToCenter does not work
msgBox.move(Utils::Gui::screenCenter(&msgBox));
msgBox.exec();
#endif
return EXIT_FAILURE;
}
bool Application::isRunning()
{

View File

@@ -46,7 +46,7 @@
#endif
#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <QThread>
#ifndef DISABLE_GUI
@@ -86,6 +86,7 @@ using namespace std::chrono_literals;
void displayVersion();
bool userAgreesWithLegalNotice();
void displayBadArgMessage(const QString &message);
void displayErrorMessage(const QString &message);
#ifndef DISABLE_GUI
void showSplashScreen();
@@ -114,10 +115,12 @@ int main(int argc, char *argv[])
Application::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
// `app` must be declared out of try block to allow display message box in case of exception
std::unique_ptr<Application> app;
try
{
// Create Application
auto app = std::make_unique<Application>(argc, argv);
app = std::make_unique<Application>(argc, argv);
#ifdef Q_OS_WIN
// QCoreApplication::applicationDirPath() needs an Application object instantiated first
@@ -268,7 +271,7 @@ int main(int argc, char *argv[])
}
catch (const RuntimeError &er)
{
qDebug() << er.message();
displayErrorMessage(er.message());
return EXIT_FAILURE;
}
}
@@ -311,6 +314,30 @@ void displayBadArgMessage(const QString &message)
#endif
}
void displayErrorMessage(const QString &message)
{
#ifndef DISABLE_GUI
if (QApplication::instance())
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(QCoreApplication::translate("Main", "An unrecoverable error occurred."));
msgBox.setInformativeText(message);
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", "qBittorrent has encountered an unrecoverable error.") + u'\n' + message + u'\n';
fprintf(stderr, "%s", qUtf8Printable(errMsg));
}
#else
const QString errMsg = QCoreApplication::translate("Main", "qBittorrent has encountered an unrecoverable error.") + u'\n' + message + u'\n';
fprintf(stderr, "%s", qUtf8Printable(errMsg));
#endif
}
bool userAgreesWithLegalNotice()
{
Preferences *const pref = Preferences::instance();

View File

@@ -2950,7 +2950,7 @@ bool SessionImpl::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &so
}
void SessionImpl::findIncompleteFiles(const TorrentInfo &torrentInfo, const Path &savePath
, const Path &downloadPath, const PathList &filePaths) const
, const Path &downloadPath, const PathList &filePaths) const
{
Q_ASSERT(filePaths.isEmpty() || (filePaths.size() == torrentInfo.filesCount()));
@@ -3143,8 +3143,16 @@ void SessionImpl::generateResumeData()
void SessionImpl::saveResumeData()
{
for (const TorrentImpl *torrent : asConst(m_torrents))
torrent->nativeHandle().save_resume_data(lt::torrent_handle::only_if_modified);
m_numResumeData += m_torrents.size();
{
// When the session is terminated due to unrecoverable error
// some of the torrent handles can be corrupted
try
{
torrent->nativeHandle().save_resume_data(lt::torrent_handle::only_if_modified);
++m_numResumeData;
}
catch (const std::exception &) {}
}
// clear queued storage move jobs except the current ongoing one
if (m_moveStorageQueue.size() > 1)

View File

@@ -51,6 +51,7 @@
#include <QStringList>
#include <QUrl>
#include "base/exceptions.h"
#include "base/global.h"
#include "base/logger.h"
#include "base/preferences.h"
@@ -1602,7 +1603,8 @@ void TorrentImpl::applyFirstLastPiecePriority(const bool enabled)
void TorrentImpl::fileSearchFinished(const Path &savePath, const PathList &fileNames)
{
endReceivedMetadataHandling(savePath, fileNames);
if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
endReceivedMetadataHandling(savePath, fileNames);
}
TrackerEntry TorrentImpl::updateTrackerEntry(const lt::announce_entry &announceEntry, const QMap<TrackerEntry::Endpoint, int> &updateInfo)
@@ -1635,7 +1637,13 @@ std::shared_ptr<const libtorrent::torrent_info> TorrentImpl::nativeTorrentInfo()
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
{
Q_ASSERT(m_maintenanceJob == MaintenanceJob::HandleMetadata);
if (Q_UNLIKELY(m_maintenanceJob != MaintenanceJob::HandleMetadata))
return;
Q_ASSERT(m_filePaths.isEmpty());
if (Q_UNLIKELY(!m_filePaths.isEmpty()))
m_filePaths.clear();
lt::add_torrent_params &p = m_ltAddTorrentParams;
@@ -1644,7 +1652,7 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
m_filePriorities.reserve(filesCount());
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
p.file_priorities = resized(p.file_priorities, metadata->files().num_files()
, LT::toNative(p.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
, LT::toNative(p.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
m_completedFiles.fill(static_cast<bool>(p.flags & lt::torrent_flags::seed_mode), filesCount());
m_filesProgress.resize(filesCount());
@@ -1694,6 +1702,7 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
}
void TorrentImpl::reload()
try
{
m_completedFiles.fill(false);
m_filesProgress.fill(0);
@@ -1736,6 +1745,11 @@ void TorrentImpl::reload()
updateState();
}
catch (const lt::system_error &err)
{
throw RuntimeError(tr("Failed to reload torrent. Torrent: %1. Reason: %2")
.arg(id().toString(), QString::fromLocal8Bit(err.what())));
}
void TorrentImpl::pause()
{

View File

@@ -62,11 +62,10 @@ public:
{
const QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies();
for (const QNetworkCookie &cookie : asConst(Preferences::instance()->getNetworkCookies()))
cookies.erase(std::remove_if(cookies.begin(), cookies.end(), [&now](const QNetworkCookie &cookie)
{
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return cookie.isSessionCookie() || (cookie.expirationDate() <= now);
}), cookies.end());
setAllCookies(cookies);
}
@@ -75,11 +74,10 @@ public:
{
const QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = allCookies();
for (const QNetworkCookie &cookie : asConst(allCookies()))
cookies.erase(std::remove_if(cookies.begin(), cookies.end(), [&now](const QNetworkCookie &cookie)
{
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return cookie.isSessionCookie() || (cookie.expirationDate() <= now);
}), cookies.end());
Preferences::instance()->setNetworkCookies(cookies);
}
@@ -91,11 +89,10 @@ public:
{
const QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url);
for (const QNetworkCookie &cookie : asConst(QNetworkCookieJar::cookiesForUrl(url)))
cookies.erase(std::remove_if(cookies.begin(), cookies.end(), [&now](const QNetworkCookie &cookie)
{
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return !cookie.isSessionCookie() && (cookie.expirationDate() <= now);
}), cookies.end());
return cookies;
}
@@ -104,11 +101,10 @@ public:
{
const QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = cookieList;
for (const QNetworkCookie &cookie : cookieList)
cookies.erase(std::remove_if(cookies.begin(), cookies.end(), [&now](const QNetworkCookie &cookie)
{
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return !cookie.isSessionCookie() && (cookie.expirationDate() <= now);
}), cookies.end());
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
}

View File

@@ -1411,7 +1411,8 @@ bool Preferences::isTorrentFileAssocSet()
if (defaultHandlerId != NULL)
{
const CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
if (myBundleId != NULL)
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
CFRelease(defaultHandlerId);
}
CFRelease(torrentId);
@@ -1423,11 +1424,13 @@ void Preferences::setTorrentFileAssoc()
{
if (isTorrentFileAssocSet())
return;
const CFStringRef torrentId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, torrentExtension, NULL);
if (torrentId != NULL)
{
const CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
LSSetDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer, myBundleId);
if (myBundleId != NULL)
LSSetDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer, myBundleId);
CFRelease(torrentId);
}
}
@@ -1439,7 +1442,8 @@ bool Preferences::isMagnetLinkAssocSet()
if (defaultHandlerId != NULL)
{
const CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
if (myBundleId != NULL)
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
CFRelease(defaultHandlerId);
}
return isSet;
@@ -1449,8 +1453,10 @@ void Preferences::setMagnetLinkAssoc()
{
if (isMagnetLinkAssocSet())
return;
const CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId);
if (myBundleId != NULL)
LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId);
}
#endif // Q_OS_MACOS

View File

@@ -271,6 +271,7 @@ void Session::load()
if (readResult.error().status == Utils::IO::ReadError::NotExist)
{
loadLegacy();
store(); // convert to new format
return;
}
@@ -294,10 +295,11 @@ void Session::load()
return;
}
loadFolder(jsonDoc.object(), rootFolder());
if (loadFolder(jsonDoc.object(), rootFolder()))
store(); // convert to updated format
}
void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
bool Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
{
bool updated = false;
for (const QString &key : asConst(jsonObj.keys()))
@@ -353,7 +355,8 @@ void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
}
else
{
loadFolder(valObj, addSubfolder(key, folder));
if (loadFolder(valObj, addSubfolder(key, folder)))
updated = true;
}
}
else
@@ -363,8 +366,7 @@ void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder)
}
}
if (updated)
store(); // convert to updated format
return updated;
}
void Session::loadLegacy()
@@ -394,8 +396,6 @@ void Session::loadLegacy()
addFeed(feedUrl, feedPath);
++i;
}
store(); // convert to new format
}
void Session::store()

View File

@@ -149,7 +149,7 @@ namespace RSS
private:
QUuid generateUID() const;
void load();
void loadFolder(const QJsonObject &jsonObj, Folder *folder);
bool loadFolder(const QJsonObject &jsonObj, Folder *folder);
void loadLegacy();
void store();
nonstd::expected<Folder *, QString> prepareItemDest(const QString &path);

View File

@@ -32,7 +32,7 @@
#define QBT_VERSION_MINOR 6
#define QBT_VERSION_BUGFIX 0
#define QBT_VERSION_BUILD 0
#define QBT_VERSION_STATUS "beta2" // Should be empty for stable releases!
#define QBT_VERSION_STATUS "RC2" // Should be empty for stable releases!
#define QBT__STRINGIFY(x) #x
#define QBT_STRINGIFY(x) QBT__STRINGIFY(x)

View File

@@ -65,7 +65,7 @@ AboutDialog::AboutDialog(QWidget *parent)
u"</p>"_s
.arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar.")
.replace(u"C++"_s, u"C\u2060+\u2060+"_s) // make C++ non-breaking
, tr("Copyright %1 2006-2022 The qBittorrent project").arg(C_COPYRIGHT)
, tr("Copyright %1 2006-2023 The qBittorrent project").arg(C_COPYRIGHT)
, tr("Home Page:")
, tr("Forum:")
, tr("Bug Tracker:"));

View File

@@ -455,8 +455,6 @@ MainWindow::MainWindow(IGUIApplication *app, WindowState initialState)
}
#endif
m_propertiesWidget->readSettings();
const bool isFiltersSidebarVisible = pref->isFiltersSidebarVisible();
m_ui->actionShowFiltersSidebar->setChecked(isFiltersSidebarVisible);
if (isFiltersSidebarVisible)
@@ -1092,6 +1090,12 @@ void MainWindow::showEvent(QShowEvent *e)
{
// preparations before showing the window
if (m_neverShown)
{
m_propertiesWidget->readSettings();
m_neverShown = false;
}
if (currentTabWidget() == m_transferListWidget)
m_propertiesWidget->loadDynamicData();

View File

@@ -202,6 +202,7 @@ private:
QFileSystemWatcher *m_executableWatcher = nullptr;
// GUI related
bool m_posInitialized = false;
bool m_neverShown = true;
QPointer<QTabWidget> m_tabs;
QPointer<StatusBar> m_statusBar;
QPointer<OptionsDialog> m_options;

View File

@@ -105,7 +105,7 @@ void PowerManagementInhibitor::requestBusy()
args << 0u;
args << u"Active torrents are presented"_s;
if (m_useGSM)
args << 8u;
args << 4u;
call.setArguments(args);
QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call, 1000);

View File

@@ -253,6 +253,16 @@ QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const
return index;
}
QModelIndexList TransferListWidget::mapToSource(const QModelIndexList &indexes) const
{
QModelIndexList result;
result.reserve(indexes.size());
for (const QModelIndex &index : indexes)
result.append(mapToSource(index));
return result;
}
QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
@@ -263,11 +273,13 @@ QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const
void TransferListWidget::torrentDoubleClicked()
{
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid()) return;
if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid())
return;
const QModelIndex index = m_listModel->index(mapToSource(selectedIndexes.first()).row());
BitTorrent::Torrent *const torrent = m_listModel->torrentHandle(index);
if (!torrent) return;
if (!torrent)
return;
int action;
if (torrent->isFinished())
@@ -806,7 +818,8 @@ void TransferListWidget::exportTorrent()
bool hasError = false;
for (const BitTorrent::Torrent *torrent : torrents)
{
const Path filePath = savePath / Path(torrent->name() + u".torrent");
const QString validName = Utils::Fs::toValidFileName(torrent->name(), u"_"_s);
const Path filePath = savePath / Path(validName + u".torrent");
if (filePath.exists())
{
LogMsg(errorMsg.arg(torrent->name(), filePath.toString(), tr("A file with the same name already exists")) , Log::WARNING);
@@ -871,9 +884,13 @@ QStringList TransferListWidget::askTagsForSelection(const QString &dialogTitle)
void TransferListWidget::applyToSelectedTorrents(const std::function<void (BitTorrent::Torrent *const)> &fn)
{
for (const QModelIndex &index : asConst(selectionModel()->selectedRows()))
// Changing the data may affect the layout of the sort/filter model, which in turn may invalidate
// the indexes previously obtained from selection model before we process them all.
// Therefore, we must map all the selected indexes to source before start processing them.
const QModelIndexList sourceRows = mapToSource(selectionModel()->selectedRows());
for (const QModelIndex &index : sourceRows)
{
BitTorrent::Torrent *const torrent = m_listModel->torrentHandle(mapToSource(index));
BitTorrent::Torrent *const torrent = m_listModel->torrentHandle(index);
Q_ASSERT(torrent);
fn(torrent);
}
@@ -882,11 +899,13 @@ void TransferListWidget::applyToSelectedTorrents(const std::function<void (BitTo
void TransferListWidget::renameSelectedTorrent()
{
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid()) return;
if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid())
return;
const QModelIndex mi = m_listModel->index(mapToSource(selectedIndexes.first()).row(), TransferListModel::TR_NAME);
BitTorrent::Torrent *const torrent = m_listModel->torrentHandle(mi);
if (!torrent) return;
if (!torrent)
return;
// Ask for a new Name
bool ok = false;
@@ -901,8 +920,7 @@ void TransferListWidget::renameSelectedTorrent()
void TransferListWidget::setSelectionCategory(const QString &category)
{
for (const QModelIndex &index : asConst(selectionModel()->selectedRows()))
m_listModel->setData(m_listModel->index(mapToSource(index).row(), TransferListModel::TR_CATEGORY), category, Qt::DisplayRole);
applyToSelectedTorrents([&category](BitTorrent::Torrent *torrent) { torrent->setCategory(category); });
}
void TransferListWidget::addSelectionTag(const QString &tag)
@@ -923,7 +941,8 @@ void TransferListWidget::clearSelectionTags()
void TransferListWidget::displayListMenu()
{
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
if (selectedIndexes.isEmpty()) return;
if (selectedIndexes.isEmpty())
return;
auto *listMenu = new QMenu(this);
listMenu->setAttribute(Qt::WA_DeleteOnClose);

View File

@@ -119,6 +119,7 @@ private slots:
private:
void wheelEvent(QWheelEvent *event) override;
QModelIndex mapToSource(const QModelIndex &index) const;
QModelIndexList mapToSource(const QModelIndexList &indexes) const;
QModelIndex mapFromSource(const QModelIndex &index) const;
bool loadSettings();
QVector<BitTorrent::Torrent *> getSelectedTorrents() const;

View File

@@ -161,13 +161,13 @@ void DefaultThemeSource::loadColors()
return;
}
const QByteArray configData = readResult.value();
const QByteArray &configData = readResult.value();
if (configData.isEmpty())
return;
const QJsonObject config = parseThemeConfig(configData);
QHash<QString, QColor> lightModeColorOverrides = colorsFromJSON(config.value(KEY_COLORS_LIGHT).toObject());
const QHash<QString, QColor> lightModeColorOverrides = colorsFromJSON(config.value(KEY_COLORS_LIGHT).toObject());
for (auto overridesIt = lightModeColorOverrides.cbegin(); overridesIt != lightModeColorOverrides.cend(); ++overridesIt)
{
auto it = m_colors.find(overridesIt.key());
@@ -175,7 +175,7 @@ void DefaultThemeSource::loadColors()
it.value().light = overridesIt.value();
}
QHash<QString, QColor> darkModeColorOverrides = colorsFromJSON(config.value(KEY_COLORS_DARK).toObject());
const QHash<QString, QColor> darkModeColorOverrides = colorsFromJSON(config.value(KEY_COLORS_DARK).toObject());
for (auto overridesIt = darkModeColorOverrides.cbegin(); overridesIt != darkModeColorOverrides.cend(); ++overridesIt)
{
auto it = m_colors.find(overridesIt.key());
@@ -184,6 +184,12 @@ void DefaultThemeSource::loadColors()
}
}
CustomThemeSource::CustomThemeSource(const Path &themeRootPath)
: m_themeRootPath {themeRootPath}
{
loadColors();
}
QColor CustomThemeSource::getColor(const QString &colorId, const ColorMode colorMode) const
{
if (colorMode == ColorMode::Dark)
@@ -246,6 +252,11 @@ DefaultThemeSource *CustomThemeSource::defaultThemeSource() const
return m_defaultThemeSource.get();
}
Path CustomThemeSource::themeRootPath() const
{
return m_themeRootPath;
}
void CustomThemeSource::loadColors()
{
const auto readResult = Utils::IO::readFile((themeRootPath() / Path(CONFIG_FILE_NAME)), FILE_MAX_SIZE, QIODevice::Text);
@@ -257,7 +268,7 @@ void CustomThemeSource::loadColors()
return;
}
const QByteArray configData = readResult.value();
const QByteArray &configData = readResult.value();
if (configData.isEmpty())
return;
@@ -267,13 +278,9 @@ void CustomThemeSource::loadColors()
m_darkModeColors.insert(colorsFromJSON(config.value(KEY_COLORS_DARK).toObject()));
}
Path QRCThemeSource::themeRootPath() const
{
return Path(u":/uitheme"_s);
}
FolderThemeSource::FolderThemeSource(const Path &folderPath)
: m_folder {folderPath}
: CustomThemeSource(folderPath)
, m_folder {folderPath}
{
}
@@ -285,10 +292,10 @@ QByteArray FolderThemeSource::readStyleSheet()
const QString stylesheetResourcesDir = u":/uitheme"_s;
QByteArray styleSheetData = CustomThemeSource::readStyleSheet();
return styleSheetData.replace(stylesheetResourcesDir.toUtf8(), themeRootPath().data().toUtf8());
return styleSheetData.replace(stylesheetResourcesDir.toUtf8(), m_folder.data().toUtf8());
}
Path FolderThemeSource::themeRootPath() const
QRCThemeSource::QRCThemeSource()
: CustomThemeSource(Path(u":/uitheme"_s))
{
return m_folder;
}

View File

@@ -84,21 +84,24 @@ public:
QByteArray readStyleSheet() override;
protected:
virtual Path themeRootPath() const = 0;
explicit CustomThemeSource(const Path &themeRootPath);
DefaultThemeSource *defaultThemeSource() const;
private:
Path themeRootPath() const;
void loadColors();
const std::unique_ptr<DefaultThemeSource> m_defaultThemeSource = std::make_unique<DefaultThemeSource>();
Path m_themeRootPath;
QHash<QString, QColor> m_colors;
QHash<QString, QColor> m_darkModeColors;
};
class QRCThemeSource final : public CustomThemeSource
{
private:
Path themeRootPath() const override;
public:
QRCThemeSource();
};
class FolderThemeSource : public CustomThemeSource
@@ -109,7 +112,5 @@ public:
QByteArray readStyleSheet() override;
private:
Path themeRootPath() const override;
const Path m_folder;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More