1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-11-14 03:17:38 +01:00

Compare commits

...

23 Commits

Author SHA1 Message Date
sledgehammer999
6ede4e49ff Bump to 5.1.3 2025-11-11 00:28:54 +02:00
sledgehammer999
7d7bfd818d Update Changelog 2025-11-11 00:26:14 +02:00
sledgehammer999
6038d6261a Sync translations from Transifex and run lupdate 2025-11-11 00:25:43 +02:00
Halbast
172089cf4f NSIS: Update Kurdish translation
PR #22801.
2025-11-10 23:41:39 +02:00
Ramon López i Cros
1ab24a22d0 NSIS: Add Catalan translation
All strings have been translated by a native Catalan speaker.

PR #23346.
2025-11-10 23:41:04 +02:00
sledgehammer999
f2c1ce585a Sync translations from Transifex and run lupdate 2025-11-08 00:23:15 +02:00
Vladimir Golovnev
f76b17155e Backport changes to v5.1.x branch
PR #22988.
2025-11-04 16:25:31 +03:00
Chocobo1
7bbe8eff51 WebUI: prefer using arrow functions
For addressing WebUI CI failures on v5_1_x branch.
2025-11-03 13:33:51 +08:00
Vladimir Golovnev
2979b1e0e4 WebAPI: Use native separators for path autofill suggestions
PR #23439.
Closes #23432.
2025-11-02 16:39:40 +03:00
Andrew Johnson
4ffb5af6aa Improve tab key focus in hidable tab bar widget
PR #23379.
2025-10-19 10:11:01 +03:00
Andrew Johnson
ba7c7e283e Fix screen reader accessibility in torrent list
PR #23359.
Closes #20393.
2025-10-15 11:12:28 +03:00
Vladimir Golovnev
571094cc9c Don't change the processing order of alerts of different types
PR #23373.
Closes #23319.
2025-10-14 13:09:49 +03:00
Vladimir Golovnev
8f1fc451ae Fix "Save as .torrent file" button is visible before metadata retrieved
PR #23375.
2025-10-14 13:03:16 +03:00
xavier2k6
0f7a27ea03 GHA CI: Install NSIS via third party action on Windows
* Install `NSIS` via https://github.com/repolevedavaj/install-nsis
* `NSIS` is no longer installed on GitHub provided Runner Image as of `windows-2025`
* `NSIS: 3.10` was only available on `windows-2019 / windows-2022`
* We can use newer release now eg. `NSIS: 3.11`.

PR #23249.
2025-10-14 12:59:38 +03:00
Mark Yu
015950ea61 Allow equals character in the command line value
The CLI options should allow the `=` (equals) char as value so doing `--save-path="/home/test/mydir = somedir"` should parse properly with the `value` method returning `"/home/test/mydir = somedir"`.

Closes #23248.
PR #23251.

---------

Co-authored-by: Vladimir Golovnev <glassez@yandex.ru>
Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
2025-10-14 12:58:18 +03:00
Vladimir Golovnev
772ba5f6bc Don't fail because of existing files when exporting torrent files
PR #23315.
Closes #23017.
2025-10-13 16:19:56 +03:00
Chocobo1
298bd20299 Fix typo
This typo is causing the header `X-Forwarded-Proto` to be ineffective
(when using reverse proxy).

PR #23120.
2025-08-24 19:22:28 +03:00
rekayno
e6f50147d9 Fix invalid Transifex links
PR #23057.
2025-08-09 17:41:51 +03:00
Chocobo1
18fb9936f0 Add alternative URL for program update checking
The alternative URL is hosted on GitHub and users are able to access it:
https://github.com/qbittorrent/qBittorrent/issues/23000#issuecomment-3092538814
https://github.com/qbittorrent/qBittorrent/issues/23009#issuecomment-3093201180

Also, disguise the user agent as a normal browser to avoid standing out from the crowd and
avoid whatever issues from CDN. This only applies to non-fosshub URLs.

Closes #23000.
Closes #23009.
PR #23014.
2025-08-09 17:41:51 +03:00
Chocobo1
3fa812ced6 Use source URL for search plugins
This saves a few URL redirections. And avoids potential issues related to Cloudflare
protections/blockages on qbt domain.

Closes #22990.
PR #23048.
2025-08-09 17:41:51 +03:00
Chocobo1
a76f12f3db Fix random function detection with static PIE builds
Certain build options didn't like the detection with an no-op. So make it really fetch a random value.

Closes #22981.
PR #22987.
2025-08-09 17:41:51 +03:00
Ryu481
d76712256c Don't leave an empty folder when deleting or moving torrents
Currently when you delete or move a torrent sometimes an empty folder will stay. This is because hidden files will stay which didn't got deleted.
The reason that it is not working is that QDir::Files is used which doesn't lists hidden files. Adding QDir::Hidden will make the code work as expected. At least on Windows and macOS QDir::Files doesn't lists hidden files. I can't test on linux.

PR #22983.
2025-08-09 17:41:41 +03:00
Ryu481
f3e47facef Fix system language autodetection on MacOS
PR #22957.
2025-07-13 21:58:51 +03:00
110 changed files with 7041 additions and 6947 deletions

View File

@@ -191,6 +191,11 @@ jobs:
name: qBittorrent-CI_Windows-x64_libtorrent-${{ matrix.libt_version }}
path: upload
- name: Install NSIS
uses: repolevedavaj/install-nsis@265e893c16602d8ccfb0a9ca44173b084078917c # v1.0.3
with:
nsis-version: '3.11'
- name: Create installer
run: |
7z x -o"dist/windows/" "dist/windows/NSISPlugins.zip"

View File

@@ -1,3 +1,20 @@
Tue Nov 11th 2025 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.1.3
- BUGFIX: Don't leave an empty folder when deleting or moving torrents (Ryu481)
- BUGFIX: Fix invalid Transifex links (rekayno)
- BUGFIX: Don't fail because of existing files when exporting torrent files (glassez)
- BUGFIX: Allow equals character in the command line value (Mark Yu)
- BUGFIX: Fix "Save as .torrent file" button being visible before metadata retrieved (glassez)
- BUGFIX: Fix crash related with the processing order of libtorrent alerts (glassez)
- BUGFIX: Fix screen reader accessibility in torrent list (Andrew Johnson)
- BUGFIX: Improve tab key focus in hidable tab bar widget (Andrew Johnson)
- WEBUI: Fix http header affecting reverse proxy (Chocobo1)
- WEBAPI: Use native separators for path autofill suggestions (glassez)
- SEARCH: Plugin updater should work again now (Chocobo1)
- WINDOWS: Program update checker should work again now (Cloudflare related) (Chocobo1)
- WINDOWS: NSIS: Add Catalan and Kurdish translations (Ramon López i Cros, Halbast)
- LINUX: Fix crashes related to getrandom() on specific setups (Chocobo1)
- MACOS: Fix system language autodetection on MacOS (Ryu481)
Wed Jul 02nd 2025 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.1.2
- BUGFIX: Don't expose palette colors in UI theme editor since they are not customizable (glassez)
- BUGFIX: Add fallback to update mechanism (sledgehammer999)

2
dist/mac/Info.plist vendored
View File

@@ -55,7 +55,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.1.2</string>
<string>5.1.3</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>

View File

@@ -161,8 +161,8 @@ Name[ta]=qBittorrent
GenericName[te]=క్యు బిట్ టొరెంట్ క్లయింట్
Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి
Name[te]=qBittorrent
GenericName[th]=ไคลเอนต์บิทอร์เรนต์
Comment[th]=ดาวน์โหลดและแชร์ไฟล์ผ่านบิตทอร์เรนต์
GenericName[th]=ไคลเอนต์บิทอร์เรนต์
Comment[th]=ดาวน์โหลดและแบ่งปันไฟล์ผ่านไฟล์บิตทอร์เรนต์
Name[th]=qBittorrent
GenericName[tr]=BitTorrent istemcisi
Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın

View File

@@ -62,6 +62,6 @@
<url type="contribute">https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md</url>
<content_rating type="oars-1.1"/>
<releases>
<release version="5.1.2" date="2025-07-02"/>
<release version="5.1.3" date="2025-11-11"/>
</releases>
</component>

View File

@@ -14,7 +14,7 @@
; 4.5.1.3 -> good
; 4.5.1.3.2 -> bad
; 4.5.0beta -> bad
!define /ifndef QBT_VERSION "5.1.2"
!define /ifndef QBT_VERSION "5.1.3"
; Option that controls the installer's window name
; If set, its value will be used like this:

View File

@@ -1,60 +1,60 @@
;Installer strings
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_CATALAN} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_CATALAN} "qBittorrent (requerit)"
;LangString inst_desktop ${LANG_ENGLISH} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_CATALAN} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_CATALAN} "Crea una drecera a l'escriptori"
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_CATALAN} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_CATALAN} "Crea una drecera al menú d'inici"
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_CATALAN} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_CATALAN} "Inicia qBittorrent en iniciar Windows"
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_CATALAN} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_CATALAN} "Obre els fitxers .torrent amb qBittorrent"
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_CATALAN} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_CATALAN} "Obre els enllaços magnètics amb qBittorrent"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_CATALAN} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_CATALAN} "Afegir la regla del tallafoc del 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_CATALAN} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_CATALAN} "Deshabilita el límit de longitud del path de Windows (260 caràcters de limitació MAX_PATH, requereix Windows 10 1607 o posterior)"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_CATALAN} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_CATALAN} "S'està afegint la regla del tallafoc del Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_CATALAN} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_CATALAN} "qBittorrent s'està executant. Tanqueu l'aplicació abans d'instal·lar."
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_CATALAN} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_CATALAN} "La versió actual es desinstal·larà. La configuració de l'usuari i els torrents es mantindran intactes."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_CATALAN} "Uninstalling previous version."
LangString inst_unist ${LANG_CATALAN} "Desinstal·lant la versió anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_CATALAN} "Launch qBittorrent."
LangString launch_qbt ${LANG_CATALAN} "Executa qBittorrent."
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_CATALAN} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_CATALAN} "Aquest instal·lador només funciona en versions Windows de 64 bits."
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_CATALAN} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_CATALAN} "Aquest instal·lador requereix almenys Windows 10 (1809) / Windows Server 2019."
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_CATALAN} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_CATALAN} "Desinstal·lar qBittorrent"
;------------------------------------
;Uninstaller strings
;LangString remove_files ${LANG_ENGLISH} "Remove files"
LangString remove_files ${LANG_CATALAN} "Remove files"
LangString remove_files ${LANG_CATALAN} "Elimina els fitxers"
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
LangString remove_shortcuts ${LANG_CATALAN} "Remove shortcuts"
LangString remove_shortcuts ${LANG_CATALAN} "Elimina les draceres"
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
LangString remove_associations ${LANG_CATALAN} "Remove file associations"
LangString remove_associations ${LANG_CATALAN} "Elimina les associacions de fitxers"
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
LangString remove_registry ${LANG_CATALAN} "Remove registry keys"
LangString remove_registry ${LANG_CATALAN} "Elimina les claus del registre"
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
LangString remove_conf ${LANG_CATALAN} "Remove configuration files"
LangString remove_conf ${LANG_CATALAN} "Elimina els fitxers de configuració"
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_CATALAN} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_CATALAN} "Elimina la regla del tallafoc del Windows"
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_CATALAN} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_CATALAN} "Eliminant la regla del tallafoc del Windows"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_CATALAN} "Remove torrents and cached data"
LangString remove_cache ${LANG_CATALAN} "Elimina els torrents i les dades de la memòria cau"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_CATALAN} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_CATALAN} "qBittorrent s'està executant. Tanca l'aplicació abans de desinstal·lar-la."
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_CATALAN} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_CATALAN} "No s'està eliminant l'associació .torrent. Està associat a:"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_CATALAN} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_CATALAN} "No s'està eliminant l'associació magnètica. Està associat a:"

View File

@@ -1,60 +1,60 @@
;Installer strings
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_KURDISH} "qBittorrent (required)"
LangString inst_qbt_req ${LANG_KURDISH} "کیووبیتتۆرێنت (پێویستە)"
;LangString inst_desktop ${LANG_ENGLISH} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_KURDISH} "Create Desktop Shortcut"
LangString inst_desktop ${LANG_KURDISH} "قەدبڕێک دروست بکە لەسەر دێسکتۆپ"
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_KURDISH} "Create Start Menu Shortcut"
LangString inst_startmenu ${LANG_KURDISH} "قەدبڕێک دروست بکە لەسەر پێڕستی دەتپێک"
;LangString inst_startup ${LANG_ENGLISH} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_KURDISH} "Start qBittorrent on Windows start up"
LangString inst_startup ${LANG_KURDISH} "لەگەڵ هەڵبوونی کۆمپیوتەرەکە کیووبیتتۆرێنت بکەرەوە"
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_KURDISH} "Open .torrent files with qBittorrent"
LangString inst_torrent ${LANG_KURDISH} "پەڕگەکانی .torrent بە کیووبیتتۆرێنت بکەرەوە"
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_KURDISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_KURDISH} "بەسەرە موگناتیسییەکان بە کیووبیتتۆرێنت بکەرەوە"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_KURDISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_KURDISH} "یاسای فایەروۆڵی ویندۆز زیاد بکە"
;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_KURDISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_KURDISH} "سنووری درێژیی ڕێڕەوی ویندۆز ناچالاک بکە (سنووری ٢٦٠ پیتی، پێویستی بە ویندۆزی ١٠ و دواتر هەیە)"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_KURDISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_KURDISH} "یاسای فایەروۆڵی ویندۆز زیاد دەبێت"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_KURDISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_KURDISH} "کیووبیتتۆرێنت کارایە. تکایە بەرنامەکە دابخەرەوە پێش دامەزراندن."
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_KURDISH} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_KURDISH} "ئەم وەشانەی ئێستا دەسڕدرێتەوە. ڕێکخستنەکانی بەکارهێنەر و تۆرێنتەکان وەک خۆیان دەمێننەوە."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_KURDISH} "Uninstalling previous version."
LangString inst_unist ${LANG_KURDISH} "وەشانی پێشوو دەسڕدرێتەوە."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_KURDISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_KURDISH} "کیووبیتتۆرێنت کارا بکە."
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_KURDISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_KURDISH} "ئەم دامەزرێنەرە تەنیا لەسەر وەشانی ٦٤ بیتی ویندۆز کار دەکات."
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_KURDISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_KURDISH} "ئەم دامەزرێنەرە لانیکەم پێویستی بە ویندۆزی ١٠ یان ویندۆز سێرڤەری ٢٠١٩ هەیە."
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_KURDISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_KURDISH} "کیووبیتتۆرێنت بسڕەوە"
;------------------------------------
;Uninstaller strings
;LangString remove_files ${LANG_ENGLISH} "Remove files"
LangString remove_files ${LANG_KURDISH} "Remove files"
LangString remove_files ${LANG_KURDISH} "پەڕگەکان بسڕەوە"
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
LangString remove_shortcuts ${LANG_KURDISH} "Remove shortcuts"
LangString remove_shortcuts ${LANG_KURDISH} "قەدبڕەکان بسڕەوە"
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
LangString remove_associations ${LANG_KURDISH} "Remove file associations"
LangString remove_associations ${LANG_KURDISH} "پەیوەندیی پەڕگەکان بسڕەوە"
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
LangString remove_registry ${LANG_KURDISH} "Remove registry keys"
LangString remove_registry ${LANG_KURDISH} "کلیلەکانی تۆمار بسڕەوە"
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
LangString remove_conf ${LANG_KURDISH} "Remove configuration files"
LangString remove_conf ${LANG_KURDISH} "پەڕگەکانی شێوەپێدان بسڕەوە"
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_KURDISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_KURDISH} "یاسای فایەروۆڵی ویندۆز بسڕەوە"
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_KURDISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_KURDISH} "یاسای فایەروۆڵی ویندۆز دەسڕێتەوە"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_KURDISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_KURDISH} "تۆرێنت و داتای کاشکراو بسڕەوە"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_KURDISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_KURDISH} "کیووبیتتۆرێنت کارایە. تکایە بەرنامەکە دابخە پێش سڕینەوەی."
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_KURDISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_KURDISH} "پەیوەندیی .torrent ناسڕێتەوە. پەیوەندیی هەیە بە:"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_KURDISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_KURDISH} "پەیوەندیی موگناتیسی ناسڕێتەوە. پەیوەیندیی هەیە بە:"

View File

@@ -86,6 +86,19 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
# Generate lproj folders for the translations
foreach(TS_FILE IN LISTS QBT_TS_FILES)
string(FIND "${TS_FILE}" "_" POS)
math(EXPR START "${POS} + 1")
string(SUBSTRING "${TS_FILE}" ${START} -1 LPROJ_FOLDER)
string(REPLACE ".ts" ".lproj" LPROJ_FOLDER "${LPROJ_FOLDER}")
# @ is not valid as a language code for a lproj folder on MacOS
string(REPLACE "@" "-" LPROJ_FOLDER "${LPROJ_FOLDER}")
add_custom_command(TARGET qbt_app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"$<TARGET_FILE_DIR:qbt_app>/../Resources/${LPROJ_FOLDER}"
)
endforeach()
# provide variables for substitution in dist/mac/Info.plist
get_target_property(EXECUTABLE_NAME qbt_app OUTPUT_NAME)
# This variable name should be changed once qmake is no longer used. Refer to the discussion in PR #14813

View File

@@ -147,12 +147,14 @@ namespace
QString value(const QString &arg) const
{
QStringList parts = arg.split(u'=');
if (parts.size() == 2)
return Utils::String::unquote(parts[1], u"'\""_s);
throw CommandLineParameterError(QCoreApplication::translate("CMD Options", "Parameter '%1' must follow syntax '%1=%2'",
const qsizetype index = arg.indexOf(u'=');
if (index == -1)
throw CommandLineParameterError(QCoreApplication::translate("CMD Options", "Parameter '%1' must follow syntax '%1=%2'",
"e.g. Parameter '--webui-port' must follow syntax '--webui-port=value'")
.arg(fullParameter(), u"<value>"_s));
const QStringView val = QStringView(arg).sliced(index + 1);
return Utils::String::unquote(val, u"'\""_s).toString();
}
QString value(const QProcessEnvironment &env, const QString &defaultValue = {}) const
@@ -168,7 +170,7 @@ namespace
friend bool operator==(const StringOption &option, const QString &arg)
{
return arg.startsWith(option.parameterAssignment());
return (arg == option.fullParameter()) || arg.startsWith(option.parameterAssignment());
}
private:

View File

@@ -3151,7 +3151,7 @@ void SessionImpl::exportTorrentFile(const Torrent *torrent, const Path &folderPa
while (newTorrentPath.exists())
{
// Append number to torrent name to make it unique
torrentExportFilename = u"%1 %2.torrent"_s.arg(validName).arg(++counter);
torrentExportFilename = u"%1 (%2).torrent"_s.arg(validName).arg(++counter);
newTorrentPath = folderPath / Path(torrentExportFilename);
}
@@ -5651,6 +5651,25 @@ void SessionImpl::fetchPendingAlerts(const lt::time_duration time)
m_nativeSession->pop_alerts(&m_alerts);
}
void SessionImpl::endAlertSequence(const int alertType, const qsizetype alertCount)
{
qDebug() << "End alert sequence. Alert:" << lt::alert_name(alertType) << "Count:" << alertCount;
if (alertType == lt::add_torrent_alert::alert_type)
{
emit addTorrentAlertsReceived(alertCount);
if (!m_loadedTorrents.isEmpty())
{
if (isRestored())
m_torrentsQueueChanged = true;
emit torrentsLoaded(m_loadedTorrents);
m_loadedTorrents.clear();
}
}
}
TorrentContentLayout SessionImpl::torrentContentLayout() const
{
return m_torrentContentLayout;
@@ -5667,28 +5686,26 @@ void SessionImpl::readAlerts()
fetchPendingAlerts();
Q_ASSERT(m_loadedTorrents.isEmpty());
Q_ASSERT(m_receivedAddTorrentAlertsCount == 0);
if (!isRestored())
m_loadedTorrents.reserve(MAX_PROCESSING_RESUMEDATA_COUNT);
int previousAlertType = -1;
qsizetype alertSequenceSize = 0;
for (const lt::alert *a : m_alerts)
handleAlert(a);
if (m_receivedAddTorrentAlertsCount > 0)
{
emit addTorrentAlertsReceived(m_receivedAddTorrentAlertsCount);
m_receivedAddTorrentAlertsCount = 0;
if (!m_loadedTorrents.isEmpty())
const int alertType = a->type();
if ((alertType != previousAlertType) && (previousAlertType != -1))
{
if (isRestored())
m_torrentsQueueChanged = true;
emit torrentsLoaded(m_loadedTorrents);
m_loadedTorrents.clear();
endAlertSequence(previousAlertType, alertSequenceSize);
alertSequenceSize = 0;
}
handleAlert(a);
++alertSequenceSize;
previousAlertType = alertType;
}
endAlertSequence(previousAlertType, alertSequenceSize);
// Some torrents may become "finished" after different alerts handling.
processPendingFinishedTorrents();
@@ -5696,8 +5713,6 @@ void SessionImpl::readAlerts()
void SessionImpl::handleAddTorrentAlert(const lt::add_torrent_alert *alert)
{
++m_receivedAddTorrentAlertsCount;
if (alert->error)
{
const QString msg = QString::fromStdString(alert->message());

View File

@@ -607,6 +607,7 @@ namespace BitTorrent
void populateAdditionalTrackersFromURL();
void fetchPendingAlerts(lt::time_duration time = lt::time_duration::zero());
void endAlertSequence(int alertType, qsizetype alertCount);
void moveTorrentStorage(const MoveStorageJob &job) const;
void handleMoveTorrentStorageJobFinished(const Path &newPath);

View File

@@ -60,7 +60,7 @@ namespace Http
inline const QString HEADER_X_CONTENT_TYPE_OPTIONS = u"x-content-type-options"_s;
inline const QString HEADER_X_FORWARDED_FOR = u"x-forwarded-for"_s;
inline const QString HEADER_X_FORWARDED_HOST = u"x-forwarded-host"_s;
inline const QString HEADER_X_FORWARDED_PROTO = u"X-forwarded-proto"_s;
inline const QString HEADER_X_FORWARDED_PROTO = u"x-forwarded-proto"_s;
inline const QString HEADER_X_FRAME_OPTIONS = u"x-frame-options"_s;
inline const QString HEADER_X_XSS_PROTECTION = u"x-xss-protection"_s;

View File

@@ -87,7 +87,7 @@ namespace
QPointer<SearchPluginManager> SearchPluginManager::m_instance = nullptr;
SearchPluginManager::SearchPluginManager()
: m_updateUrl(u"https://searchplugins.qbittorrent.org/nova3/engines/"_s)
: m_updateUrl(u"https://raw.githubusercontent.com/qbittorrent/search-plugins/refs/heads/master/nova3/engines/"_s)
{
Q_ASSERT(!m_instance); // only one instance is allowed
m_instance = this;

View File

@@ -104,7 +104,7 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const Path &path)
if (!dir.isEmpty(QDir::Dirs | QDir::NoDotAndDotDot))
continue;
const QStringList tmpFileList = dir.entryList(QDir::Files);
const QStringList tmpFileList = dir.entryList(QDir::Files | QDir::Hidden);
// deleteFilesList contains unwanted files, usually created by the OS
// temp files on linux usually end with '~', e.g. `filename~`

View File

@@ -45,7 +45,7 @@ namespace
RandomLayer()
{
if (::getrandom(nullptr, 0, 0) < 0)
if (unsigned char buf = 0; ::getrandom(&buf, sizeof(buf), 0) < 0)
{
if (errno == ENOSYS)
{

View File

@@ -30,7 +30,7 @@
#define QBT_VERSION_MAJOR 5
#define QBT_VERSION_MINOR 1
#define QBT_VERSION_BUGFIX 2
#define QBT_VERSION_BUGFIX 3
#define QBT_VERSION_BUILD 0
#define QBT_VERSION_STATUS "" // Should be empty for stable releases!

View File

@@ -508,7 +508,7 @@ void AddNewTorrentDialog::setCurrentContext(const std::shared_ptr<Context> conte
{
m_ui->lblMetaLoading->setVisible(false);
m_ui->progMetaLoading->setVisible(false);
m_ui->buttonSave->setVisible(false);
m_ui->buttonSave->setVisible(true);
setupTreeview();
}
else
@@ -520,6 +520,7 @@ void AddNewTorrentDialog::setCurrentContext(const std::shared_ptr<Context> conte
m_ui->labelDateData->setText(tr("Not Available", "This date is unavailable"));
updateDiskSpaceLabel();
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
m_ui->buttonSave->setVisible(false);
}
TMMChanged(m_ui->comboTMM->currentIndex());

View File

@@ -38,19 +38,28 @@
HidableTabWidget::HidableTabWidget(QWidget *parent)
: QTabWidget(parent)
{
// Skip single tab in keyboard navigation (no point navigating to it)
tabBar()->setFocusPolicy(Qt::NoFocus);
}
void HidableTabWidget::tabInserted(const int index)
{
QTabWidget::tabInserted(index);
tabBar()->setVisible(count() != 1);
tabsCountChanged();
}
void HidableTabWidget::tabRemoved(const int index)
{
//QTabWidget::tabInserted(index);
QTabWidget::tabRemoved(index);
tabBar()->setVisible(count() != 1);
tabsCountChanged();
}
void HidableTabWidget::tabsCountChanged()
{
const qsizetype tabsCount = count();
tabBar()->setVisible(tabsCount != 1);
// Skip single tab in keyboard navigation (no point navigating to it)
tabBar()->setFocusPolicy((tabsCount > 1) ? Qt::StrongFocus : Qt::NoFocus);
}
#ifdef Q_OS_MACOS

View File

@@ -42,6 +42,7 @@ public:
private:
void tabInserted(int index) override;
void tabRemoved(int index) override;
void tabsCountChanged();
#ifdef Q_OS_MACOS
void paintEvent(QPaintEvent *event) override;

View File

@@ -1660,7 +1660,7 @@ void MainWindow::handleUpdateCheckFinished(ProgramUpdater *updater, const bool i
updater->deleteLater();
};
const auto newVersion = updater->getNewVersion();
const ProgramUpdater::Version newVersion = updater->getNewVersion();
if (newVersion.isValid())
{
const QString msg {tr("A new version is available.") + u"<br/>"

View File

@@ -29,6 +29,8 @@
#include "programupdater.h"
#include <algorithm>
#include <libtorrent/version.hpp>
#include <QtCore/qconfig.h>
@@ -44,7 +46,6 @@
#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/preferences.h"
#include "base/utils/version.h"
#include "base/version.h"
namespace
@@ -80,32 +81,50 @@ namespace
}
}
void ProgramUpdater::checkForUpdates() const
void ProgramUpdater::checkForUpdates()
{
const auto USER_AGENT = QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)");
const auto RSS_URL = u"https://www.fosshub.com/feed/5b8793a7f9ee5a5c3e97a3b2.xml"_s;
const auto FALLBACK_URL = u"https://www.qbittorrent.org/versions.json"_s;
// Don't change this User-Agent. In case our updater goes haywire,
// the filehost can identify it and contact us.
Net::DownloadManager::instance()->download(Net::DownloadRequest(RSS_URL).userAgent(USER_AGENT)
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::rssDownloadFinished);
Net::DownloadManager::instance()->download(Net::DownloadRequest(FALLBACK_URL).userAgent(USER_AGENT)
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::fallbackDownloadFinished);
const auto USER_AGENT = QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)");
const auto FOSSHUB_URL = u"https://www.fosshub.com/feed/5b8793a7f9ee5a5c3e97a3b2.xml"_s;
const auto QBT_MAIN_URL = u"https://www.qbittorrent.org/versions.json"_s;
const auto QBT_BACKUP_URL = u"https://qbittorrent.github.io/qBittorrent-website/versions.json"_s;
m_hasCompletedOneReq = false;
Net::DownloadManager *netManager = Net::DownloadManager::instance();
const bool useProxy = Preferences::instance()->useProxyForGeneralPurposes();
m_pendingRequestCount = 3;
netManager->download(Net::DownloadRequest(FOSSHUB_URL).userAgent(USER_AGENT), useProxy, this, &ProgramUpdater::rssDownloadFinished);
// don't use the custom user agent for the following requests, disguise as a normal browser instead
netManager->download(Net::DownloadRequest(QBT_MAIN_URL), useProxy, this, [this](const Net::DownloadResult &result)
{
fallbackDownloadFinished(result, m_qbtMainVersion);
});
netManager->download(Net::DownloadRequest(QBT_BACKUP_URL), useProxy, this, [this](const Net::DownloadResult &result)
{
fallbackDownloadFinished(result, m_qbtBackupVersion);
});
}
ProgramUpdater::Version ProgramUpdater::getNewVersion() const
{
return shouldUseFallback() ? m_fallbackRemoteVersion : m_remoteVersion;
switch (getLatestRemoteSource())
{
case RemoteSource::Fosshub:
return m_fosshubVersion;
case RemoteSource::QbtMain:
return m_qbtMainVersion;
case RemoteSource::QbtBackup:
return m_qbtBackupVersion;
}
Q_UNREACHABLE();
}
void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
{
if (result.status != Net::DownloadStatus::Success)
{
LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
LogMsg(tr("Failed to download the program update info. URL: \"%1\". Error: \"%2\"").arg(result.url, result.errorString) , Log::WARNING);
handleFinishedRequest();
return;
}
@@ -150,10 +169,10 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
if (!version.isEmpty())
{
qDebug("Detected version is %s", qUtf8Printable(version));
const ProgramUpdater::Version tmpVer {version};
const Version tmpVer {version};
if (isVersionMoreRecent(tmpVer))
{
m_remoteVersion = tmpVer;
m_fosshubVersion = tmpVer;
m_updateURL = updateLink;
}
}
@@ -171,11 +190,13 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
handleFinishedRequest();
}
void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result)
void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result, Version &version)
{
version = {};
if (result.status != Net::DownloadStatus::Success)
{
LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
LogMsg(tr("Failed to download the program update info. URL: \"%1\". Error: \"%2\"").arg(result.url, result.errorString) , Log::WARNING);
handleFinishedRequest();
return;
}
@@ -190,9 +211,9 @@ void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result)
if (const QJsonValue verJSON = json[platformKey][u"version"_s]; verJSON.isString())
{
const ProgramUpdater::Version tmpVer {verJSON.toString()};
const Version tmpVer {verJSON.toString()};
if (isVersionMoreRecent(tmpVer))
m_fallbackRemoteVersion = tmpVer;
version = tmpVer;
}
handleFinishedRequest();
@@ -200,18 +221,33 @@ void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result)
bool ProgramUpdater::updateProgram() const
{
return QDesktopServices::openUrl(shouldUseFallback() ? u"https://www.qbittorrent.org/download"_s : m_updateURL);
switch (getLatestRemoteSource())
{
case RemoteSource::Fosshub:
return QDesktopServices::openUrl(m_updateURL);
case RemoteSource::QbtMain:
return QDesktopServices::openUrl(u"https://www.qbittorrent.org/download"_s);
case RemoteSource::QbtBackup:
return QDesktopServices::openUrl(u"https://qbittorrent.github.io/qBittorrent-website/download"_s);
}
Q_UNREACHABLE();
}
void ProgramUpdater::handleFinishedRequest()
{
if (m_hasCompletedOneReq)
--m_pendingRequestCount;
if (m_pendingRequestCount == 0)
emit updateCheckFinished();
else
m_hasCompletedOneReq = true;
}
bool ProgramUpdater::shouldUseFallback() const
ProgramUpdater::RemoteSource ProgramUpdater::getLatestRemoteSource() const
{
return m_fallbackRemoteVersion > m_remoteVersion;
const Version max = std::max({m_fosshubVersion, m_qbtMainVersion, m_qbtBackupVersion});
if (max == m_fosshubVersion)
return RemoteSource::Fosshub;
if (max == m_qbtMainVersion)
return RemoteSource::QbtMain;
if (max == m_qbtBackupVersion)
return RemoteSource::QbtBackup;
Q_UNREACHABLE();
}

View File

@@ -45,10 +45,11 @@ class ProgramUpdater final : public QObject
Q_DISABLE_COPY_MOVE(ProgramUpdater)
public:
using QObject::QObject;
using Version = Utils::Version<4, 3>;
void checkForUpdates() const;
using QObject::QObject;
void checkForUpdates();
Version getNewVersion() const;
bool updateProgram() const;
@@ -57,14 +58,22 @@ signals:
private slots:
void rssDownloadFinished(const Net::DownloadResult &result);
void fallbackDownloadFinished(const Net::DownloadResult &result);
void fallbackDownloadFinished(const Net::DownloadResult &result, Version &version);
private:
void handleFinishedRequest();
bool shouldUseFallback() const;
enum class RemoteSource
{
Fosshub,
QbtMain,
QbtBackup
};
mutable bool m_hasCompletedOneReq = false;
Version m_remoteVersion;
Version m_fallbackRemoteVersion;
void handleFinishedRequest();
RemoteSource getLatestRemoteSource() const;
int m_pendingRequestCount = 0;
Version m_fosshubVersion;
Version m_qbtMainVersion;
Version m_qbtBackupVersion;
QUrl m_updateURL;
};

View File

@@ -819,21 +819,21 @@ void TransferListWidget::exportTorrent()
bool hasError = false;
for (const BitTorrent::Torrent *torrent : torrents)
{
const QString validName = Utils::Fs::toValidFileName(torrent->name(), u"_"_s);
const Path filePath = savePath / Path(validName + u".torrent");
if (filePath.exists())
const QString validName = Utils::Fs::toValidFileName(torrent->name());
QString torrentExportFilename = u"%1.torrent"_s.arg(validName);
Path newTorrentPath = savePath / Path(torrentExportFilename);
int counter = 0;
while (newTorrentPath.exists())
{
LogMsg(errorMsg.arg(torrent->name(), filePath.toString(), tr("A file with the same name already exists")) , Log::WARNING);
hasError = true;
continue;
// Append number to torrent name to make it unique
torrentExportFilename = u"%1 (%2).torrent"_s.arg(validName).arg(++counter);
newTorrentPath = savePath / Path(torrentExportFilename);
}
const nonstd::expected<void, QString> result = torrent->exportToFile(filePath);
if (!result)
if (const nonstd::expected<void, QString> result = torrent->exportToFile(newTorrentPath); !result)
{
LogMsg(errorMsg.arg(torrent->name(), filePath.toString(), result.error()) , Log::WARNING);
LogMsg(errorMsg.arg(torrent->name(), newTorrentPath.toString(), result.error()) , Log::WARNING);
hasError = true;
continue;
}
}
@@ -1285,9 +1285,16 @@ void TransferListWidget::displayListMenu()
listMenu->popup(QCursor::pos());
}
void TransferListWidget::currentChanged(const QModelIndex &current, const QModelIndex&)
void TransferListWidget::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
qDebug("CURRENT CHANGED");
// Call base class to ensure Qt's accessibility system is notified of focus changes.
// This is critical for screen readers to announce the currently selected torrent.
// Without this call, users relying on assistive technologies cannot effectively
// navigate the torrent list with keyboard arrow keys.
QTreeView::currentChanged(current, previous);
BitTorrent::Torrent *torrent = nullptr;
if (current.isValid())
{

View File

@@ -110,7 +110,7 @@ private slots:
void torrentDoubleClicked();
void displayListMenu();
void displayColumnHeaderMenu();
void currentChanged(const QModelIndex &current, const QModelIndex&) override;
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override;
void setSelectedTorrentsSuperSeeding(bool enabled) const;
void setSelectedTorrentsSequentialDownload(bool enabled) const;
void setSelectedFirstLastPiecePrio(bool enabled) const;

View File

@@ -6,7 +6,7 @@
</head>
<body>
<p>I would like to thank the people who volunteered to translate qBittorrent.<br>
Most of them translated via <a href="https://www.transifex.com/sledgehammer999/qbittorrent">Transifex</a> and some of them are mentioned below:<br>
Most of them translated via <a href="https://explore.transifex.com/sledgehammer999/qbittorrent/">Transifex</a> and some of them are mentioned below:<br>
(the list might not be up to date)
</p>
<ul>

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