You've already forked qBittorrent
							
							
				mirror of
				https://github.com/qbittorrent/qBittorrent
				synced 2025-10-30 23:30:54 +01:00 
			
		
		
		
	Compare commits
	
		
			39 Commits
		
	
	
		
			release-4.
			...
			release-3.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d753988729 | ||
|   | a6b948077a | ||
|   | 3276cc4987 | ||
|   | 71557fe784 | ||
|   | 29fc5bc80d | ||
|   | db07551e4c | ||
|   | 8f6eb795e3 | ||
|   | 0a37799e6e | ||
|   | 76d6d9a4f9 | ||
|   | 0c8abd0abb | ||
|   | ddc8420810 | ||
|   | a4ff039abc | ||
|   | c8be062e19 | ||
|   | 29443a2c10 | ||
|   | e402556e91 | ||
|   | 4ed4ebcdb7 | ||
|   | a280467270 | ||
|   | 9b1090332b | ||
|   | 18a520c9f9 | ||
|   | af871ef8af | ||
|   | 3af7eb8e03 | ||
|   | 3439300cda | ||
|   | a8027565c9 | ||
|   | 3d4e1a8127 | ||
|   | 7b6a1a1955 | ||
|   | 3f8dc60680 | ||
|   | 9be449dd7f | ||
|   | c46f2ba097 | ||
|   | c2c441ed08 | ||
|   | c1e52fa1cd | ||
|   | fbed5dc606 | ||
|   | 97978068c6 | ||
|   | 006e34880a | ||
|   | 1fd5c5d8b5 | ||
|   | 68ac9fda2d | ||
|   | c5d807ef65 | ||
|   | e17f10ae6b | ||
|   | 78c5d1c12f | ||
|   | 26fb54299b | 
| @@ -1,7 +1,7 @@ | |||||||
| [main] | [main] | ||||||
| host = https://www.transifex.com | host = https://www.transifex.com | ||||||
|  |  | ||||||
| [qbittorrent.qbittorrent_master] | [qbittorrent.qbittorrent_v3_3_x] | ||||||
| file_filter = src/lang/qbittorrent_<lang>.ts | file_filter = src/lang/qbittorrent_<lang>.ts | ||||||
| source_file = src/lang/qbittorrent_en.ts | source_file = src/lang/qbittorrent_en.ts | ||||||
| source_lang = en | source_lang = en | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | # Filing an issue | ||||||
|  |  | ||||||
|  | ### Must read | ||||||
|  | * If you aren't sure, you can ask on the [**forum**](http://forum.qbittorrent.org) or read our [**wiki**](http://wiki.qbittorrent.org) first. | ||||||
|  | * Do a quick **search**. Others might already reported the issue. | ||||||
|  | * Write in **English**! | ||||||
|  | * Provide **version** information: (You can find version numbers at menu `Help -> About -> Libraries`) | ||||||
|  |   ``` | ||||||
|  | qBittorrent: | ||||||
|  | Qt: | ||||||
|  | libtorrent: | ||||||
|  | boost: | ||||||
|  | OS version: | ||||||
|  |  | ||||||
|  |   ``` | ||||||
|  | * Provide **steps** to reproduce the problem, it will be easier to pinpoint the fault. | ||||||
|  | * **Screenshots**! A screenshot is worth a thousand words. just upload it. [(How?)](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests) | ||||||
|  |  | ||||||
|  | ### Good to know | ||||||
|  | * **Patience**. The dev team is small and resource limited. Devs finding their free time, analyzing the problem and fixing the issue, it all takes time. :clock3: | ||||||
|  | * If you can code, why not become a **contributor** by fixing the issue and open a pull request? :wink: | ||||||
|  | * Harsh words or threats won't help your situation. What's worse, your complain will (very likely) to be **ignored**. :fearful: | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Opening a pull request | ||||||
|  |  | ||||||
|  | ### Must read | ||||||
|  | * Read our [**coding guidelines**](https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md). There are some scripts to help you: [uncrustify script](https://gist.github.com/sledgehammer999/1cb1d9224d7fec8fa632), [astyle script](https://gist.github.com/Chocobo1/539cee860d1eef0acfa6), [(related thread)](https://github.com/qbittorrent/qBittorrent/issues/2192). | ||||||
|  | * Keep the title **short** and provide a **clear** description about what your pull request does. | ||||||
|  | * Provide **screenshots** for UI related changes. | ||||||
|  | * Keep your git commit history **clean** and **precise**. Commits like `xxx fixup` should not appear. | ||||||
|  | * If your commit fix a reported issue (for example #4134), add the following message to the commit `Closes #4134.`. Example [here](https://github.com/qbittorrent/qBittorrent/commit/a74bac20c4e8de9776bf9bb77fdc7526135d1988). | ||||||
|  |  | ||||||
|  | ### Good to know | ||||||
|  | * **Search** pull request history! Others might already implemented your idea and is waiting to be merged (or got rejected already). Save your precious time by doing a search first. | ||||||
|  | * When resolving merge conflicts, do `git rebase <target_branch_name>`, don't do `git pull`. Then you can start fixing the conflicts. Here is a good explanation: [link](https://www.atlassian.com/git/tutorials/merging-vs-rebasing). | ||||||
							
								
								
									
										24
									
								
								Changelog
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Changelog
									
									
									
									
									
								
							| @@ -1,3 +1,27 @@ | |||||||
|  | * Tue Dec 08 2015 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.1 | ||||||
|  |     - FEATURE: New "Set as default label" option in Add torrent dialog. (takiz) | ||||||
|  |     - FEATURE: Support wildcards for filtering torrent list and torrent content (vlakoff) | ||||||
|  |     - BUGFIX: Fix -1 is displayed instead of the infinity symbol (Chocobo1) | ||||||
|  |     - BUGFIX: Fix scan dirs settings saving. Closes #4254, #4239, #4187. (glassez) | ||||||
|  |     - BUGFIX: Exported torrents now use name instead of hash. Closes #4205. (glassez) | ||||||
|  |     - BUGFIX: Improve upgrade to v3.3.0. Now undownloaded magnets will be migrated too. Fixes #4195. (glassez) | ||||||
|  |     - BUGFIX: Fix wrong encoding for listen failed error message. (glassez) | ||||||
|  |     - BUGFIX: Fix RSS not automarking articles as read. (glassez) | ||||||
|  |     - BUGFIX: Fix possible deadlock during application exit. (sledgehammer999) | ||||||
|  |     - WEBUI: Cookies support on WebUI when downloading torrent from a URL. (Naikel Aparicio) | ||||||
|  |     - WEBUI: Modified download and upload windows to allow autocompletion of browsers. (Naikel Aparicio) | ||||||
|  |     - WEBUI: Fixed the spinner in the WebUI upload page. (Naikel Aparicio) | ||||||
|  |     - WEBUI: Modified height of the WebUI download page. (Naikel Aparicio) | ||||||
|  |     - WEBUI: Fixed all the JavaScript functions for download and upload pages. (Naikel Aparicio) | ||||||
|  |     - WEBUI: Add seeds tab to WebUI (buinsky) | ||||||
|  |     - WEBUI: Bump WebUI API_VERSION. | ||||||
|  |     - COSMETIC: Cleanup "Trackers", "Peers", "HTTP Sources", "Speed" and "Content" page layout (Chocobo1) | ||||||
|  |     - COSMETIC: Reduce mainwindow border width (Chocobo1) | ||||||
|  |     - COSMETIC: Use QLineEdit built-in ClearButton (Qt5 only) (Chocobo1) | ||||||
|  |     - COSMETIC: Change text description for half-open connection (Chocobo1) | ||||||
|  |     - OTHER: Change update URL to FossHub. Closes #4188. (sledgehammer999) | ||||||
|  |      | ||||||
|  |  | ||||||
| * Sun Nov 29 2015 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.0 | * Sun Nov 29 2015 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.0 | ||||||
|     - FEATURE: Huge core code refactoring. Problems with labels, temp folders etc should be eliminated. Smoother UI should be observed too. (glassez) |     - FEATURE: Huge core code refactoring. Problems with labels, temp folders etc should be eliminated. Smoother UI should be observed too. (glassez) | ||||||
|     - FEATURE: Speed graph (Anton Lashkov) |     - FEATURE: Speed graph (Anton Lashkov) | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								dist/mac/Info.plist
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/mac/Info.plist
									
									
									
									
										vendored
									
									
								
							| @@ -45,7 +45,7 @@ | |||||||
| 	<key>CFBundlePackageType</key> | 	<key>CFBundlePackageType</key> | ||||||
| 	<string>APPL</string> | 	<string>APPL</string> | ||||||
| 	<key>CFBundleShortVersionString</key> | 	<key>CFBundleShortVersionString</key> | ||||||
| 	<string>3.3.0</string> | 	<string>3.3.1</string> | ||||||
| 	<key>CFBundleSignature</key> | 	<key>CFBundleSignature</key> | ||||||
| 	<string>qBit</string> | 	<string>qBit</string> | ||||||
| 	<key>CFBundleExecutable</key> | 	<key>CFBundleExecutable</key> | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								dist/windows/README.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								dist/windows/README.txt
									
									
									
									
										vendored
									
									
								
							| @@ -41,7 +41,10 @@ installer-translations | |||||||
| translations | translations | ||||||
| 	qt_ar.qm | 	qt_ar.qm | ||||||
| 	... | 	... | ||||||
|         (all the .qm files found in dist/qt-translations in every source release) |         (all the .qm files found in the 'translations' folder of your Qt install. Those files differ between Qt4 and Qt5. | ||||||
|  | 	 If you want to distribute Qt4 translations it is better to use the ones found in this repo under the path "dist/qt-translations". | ||||||
|  | 	 They contain extra languages not distributed via the official qt4 sources. | ||||||
|  | 	 Don't forget to edit the filelist in installer.nsi + uninstaller.nsi to include all your .qm files.) | ||||||
| 	qt_zh_TW.qm | 	qt_zh_TW.qm | ||||||
| installer.nsi | installer.nsi | ||||||
| license.txt | license.txt | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								dist/windows/installer.nsi
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								dist/windows/installer.nsi
									
									
									
									
										vendored
									
									
								
							| @@ -31,13 +31,13 @@ Section $(inst_qbt_req) ;"qBittorrent (required)" | |||||||
|   File "qbittorrent.pdb" |   File "qbittorrent.pdb" | ||||||
|   File "qt.conf" |   File "qt.conf" | ||||||
|   File /oname=translations\qt_ar.qm "translations\qt_ar.qm" |   File /oname=translations\qt_ar.qm "translations\qt_ar.qm" | ||||||
|   File /oname=translations\qt_bg.qm "translations\qt_bg.qm" |  | ||||||
|   File /oname=translations\qt_ca.qm "translations\qt_ca.qm" |   File /oname=translations\qt_ca.qm "translations\qt_ca.qm" | ||||||
|   File /oname=translations\qt_cs.qm "translations\qt_cs.qm" |   File /oname=translations\qt_cs.qm "translations\qt_cs.qm" | ||||||
|   File /oname=translations\qt_da.qm "translations\qt_da.qm" |   File /oname=translations\qt_da.qm "translations\qt_da.qm" | ||||||
|   File /oname=translations\qt_de.qm "translations\qt_de.qm" |   File /oname=translations\qt_de.qm "translations\qt_de.qm" | ||||||
|  |   File /oname=translations\qt_en.qm "translations\qt_en.qm" | ||||||
|   File /oname=translations\qt_es.qm "translations\qt_es.qm" |   File /oname=translations\qt_es.qm "translations\qt_es.qm" | ||||||
|   File /oname=translations\qt_eu.qm "translations\qt_eu.qm"   |   File /oname=translations\qt_fa.qm "translations\qt_fa.qm" | ||||||
|   File /oname=translations\qt_fi.qm "translations\qt_fi.qm" |   File /oname=translations\qt_fi.qm "translations\qt_fi.qm" | ||||||
|   File /oname=translations\qt_fr.qm "translations\qt_fr.qm" |   File /oname=translations\qt_fr.qm "translations\qt_fr.qm" | ||||||
|   File /oname=translations\qt_gl.qm "translations\qt_gl.qm" |   File /oname=translations\qt_gl.qm "translations\qt_gl.qm" | ||||||
| @@ -47,14 +47,12 @@ Section $(inst_qbt_req) ;"qBittorrent (required)" | |||||||
|   File /oname=translations\qt_ja.qm "translations\qt_ja.qm" |   File /oname=translations\qt_ja.qm "translations\qt_ja.qm" | ||||||
|   File /oname=translations\qt_ko.qm "translations\qt_ko.qm" |   File /oname=translations\qt_ko.qm "translations\qt_ko.qm" | ||||||
|   File /oname=translations\qt_lt.qm "translations\qt_lt.qm" |   File /oname=translations\qt_lt.qm "translations\qt_lt.qm" | ||||||
|   File /oname=translations\qt_nl.qm "translations\qt_nl.qm" |  | ||||||
|   File /oname=translations\qt_pl.qm "translations\qt_pl.qm" |   File /oname=translations\qt_pl.qm "translations\qt_pl.qm" | ||||||
|   File /oname=translations\qt_pt.qm "translations\qt_pt.qm" |   File /oname=translations\qt_pt.qm "translations\qt_pt.qm" | ||||||
|   File /oname=translations\qt_pt_BR.qm "translations\qt_pt_BR.qm" |  | ||||||
|   File /oname=translations\qt_ru.qm "translations\qt_ru.qm" |   File /oname=translations\qt_ru.qm "translations\qt_ru.qm" | ||||||
|   File /oname=translations\qt_sk.qm "translations\qt_sk.qm" |   File /oname=translations\qt_sk.qm "translations\qt_sk.qm" | ||||||
|  |   File /oname=translations\qt_sl.qm "translations\qt_sl.qm" | ||||||
|   File /oname=translations\qt_sv.qm "translations\qt_sv.qm" |   File /oname=translations\qt_sv.qm "translations\qt_sv.qm" | ||||||
|   File /oname=translations\qt_tr.qm "translations\qt_tr.qm" |  | ||||||
|   File /oname=translations\qt_uk.qm "translations\qt_uk.qm" |   File /oname=translations\qt_uk.qm "translations\qt_uk.qm" | ||||||
|   File /oname=translations\qt_zh_CN.qm "translations\qt_zh_CN.qm" |   File /oname=translations\qt_zh_CN.qm "translations\qt_zh_CN.qm" | ||||||
|   File /oname=translations\qt_zh_TW.qm "translations\qt_zh_TW.qm" |   File /oname=translations\qt_zh_TW.qm "translations\qt_zh_TW.qm" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								dist/windows/options.nsi
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/windows/options.nsi
									
									
									
									
										vendored
									
									
								
							| @@ -19,7 +19,7 @@ XPStyle on | |||||||
| !define CSIDL_APPDATA '0x1A' ;Application Data path | !define CSIDL_APPDATA '0x1A' ;Application Data path | ||||||
| !define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path | !define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path | ||||||
|  |  | ||||||
| !define PROG_VERSION "3.3.0" | !define PROG_VERSION "3.3.1" | ||||||
| !define MUI_FINISHPAGE_RUN | !define MUI_FINISHPAGE_RUN | ||||||
| !define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun | !define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun | ||||||
| !define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt) | !define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt) | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								dist/windows/uninstaller.nsi
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								dist/windows/uninstaller.nsi
									
									
									
									
										vendored
									
									
								
							| @@ -6,13 +6,12 @@ | |||||||
|   Delete "$INSTDIR\qbittorrent.pdb" |   Delete "$INSTDIR\qbittorrent.pdb" | ||||||
|   Delete "$INSTDIR\qt.conf"   |   Delete "$INSTDIR\qt.conf"   | ||||||
|   Delete "$INSTDIR\translations\qt_ar.qm" |   Delete "$INSTDIR\translations\qt_ar.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_bg.qm" |  | ||||||
|   Delete "$INSTDIR\translations\qt_ca.qm" |   Delete "$INSTDIR\translations\qt_ca.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_cs.qm" |   Delete "$INSTDIR\translations\qt_cs.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_da.qm" |   Delete "$INSTDIR\translations\qt_da.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_de.qm" |   Delete "$INSTDIR\translations\qt_de.qm" | ||||||
|  |   Delete "$INSTDIR\translations\qt_en.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_es.qm" |   Delete "$INSTDIR\translations\qt_es.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_eu.qm" |  | ||||||
|   Delete "$INSTDIR\translations\qt_fa.qm" |   Delete "$INSTDIR\translations\qt_fa.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_fi.qm" |   Delete "$INSTDIR\translations\qt_fi.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_fr.qm" |   Delete "$INSTDIR\translations\qt_fr.qm" | ||||||
| @@ -23,15 +22,12 @@ | |||||||
|   Delete "$INSTDIR\translations\qt_ja.qm" |   Delete "$INSTDIR\translations\qt_ja.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_ko.qm" |   Delete "$INSTDIR\translations\qt_ko.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_lt.qm" |   Delete "$INSTDIR\translations\qt_lt.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_nl.qm" |  | ||||||
|   Delete "$INSTDIR\translations\qt_pl.qm" |   Delete "$INSTDIR\translations\qt_pl.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_pt.qm" |   Delete "$INSTDIR\translations\qt_pt.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_pt_BR.qm" |  | ||||||
|   Delete "$INSTDIR\translations\qt_ru.qm" |   Delete "$INSTDIR\translations\qt_ru.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_sk.qm" |   Delete "$INSTDIR\translations\qt_sk.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_sl.qm" |   Delete "$INSTDIR\translations\qt_sl.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_sv.qm" |   Delete "$INSTDIR\translations\qt_sv.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_tr.qm" |  | ||||||
|   Delete "$INSTDIR\translations\qt_uk.qm" |   Delete "$INSTDIR\translations\qt_uk.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_zh_CN.qm" |   Delete "$INSTDIR\translations\qt_zh_CN.qm" | ||||||
|   Delete "$INSTDIR\translations\qt_zh_TW.qm" |   Delete "$INSTDIR\translations\qt_zh_TW.qm" | ||||||
|   | |||||||
| @@ -58,17 +58,17 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "application.h" | #include "application.h" | ||||||
| #include "core/logger.h" | #include "base/logger.h" | ||||||
| #include "core/preferences.h" | #include "base/preferences.h" | ||||||
| #include "core/utils/fs.h" | #include "base/utils/fs.h" | ||||||
| #include "core/utils/misc.h" | #include "base/utils/misc.h" | ||||||
| #include "core/iconprovider.h" | #include "base/iconprovider.h" | ||||||
| #include "core/scanfoldersmodel.h" | #include "base/scanfoldersmodel.h" | ||||||
| #include "core/net/smtp.h" | #include "base/net/smtp.h" | ||||||
| #include "core/net/downloadmanager.h" | #include "base/net/downloadmanager.h" | ||||||
| #include "core/net/geoipmanager.h" | #include "base/net/geoipmanager.h" | ||||||
| #include "core/bittorrent/session.h" | #include "base/bittorrent/session.h" | ||||||
| #include "core/bittorrent/torrenthandle.h" | #include "base/bittorrent/torrenthandle.h" | ||||||
|  |  | ||||||
| static const char PARAMS_SEPARATOR[] = "|"; | static const char PARAMS_SEPARATOR[] = "|"; | ||||||
|  |  | ||||||
| @@ -357,7 +357,7 @@ void Application::initializeTranslation() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (m_qtTranslator.load( |     if (m_qtTranslator.load( | ||||||
| #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) | #ifdef QBT_USES_QT5 | ||||||
|             QString::fromUtf8("qtbase_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) || |             QString::fromUtf8("qtbase_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) || | ||||||
|         m_qtTranslator.load( |         m_qtTranslator.load( | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ QT_END_NAMESPACE | |||||||
| typedef QtSingleCoreApplication BaseApplication; | typedef QtSingleCoreApplication BaseApplication; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "core/utils/misc.h" | #include "base/utils/misc.h" | ||||||
|  |  | ||||||
| #ifndef DISABLE_WEBUI | #ifndef DISABLE_WEBUI | ||||||
| class WebUI; | class WebUI; | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ | |||||||
| #include <QSplashScreen> | #include <QSplashScreen> | ||||||
| #ifdef QBT_STATIC_QT | #ifdef QBT_STATIC_QT | ||||||
| #include <QtPlugin> | #include <QtPlugin> | ||||||
| #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) | #ifdef QBT_USES_QT5 | ||||||
| Q_IMPORT_PLUGIN(QICOPlugin) | Q_IMPORT_PLUGIN(QICOPlugin) | ||||||
| #else | #else | ||||||
| Q_IMPORT_PLUGIN(qico) | Q_IMPORT_PLUGIN(qico) | ||||||
| @@ -72,8 +72,8 @@ Q_IMPORT_PLUGIN(qico) | |||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include "application.h" | #include "application.h" | ||||||
| #include "core/utils/misc.h" | #include "base/utils/misc.h" | ||||||
| #include "core/preferences.h" | #include "base/preferences.h" | ||||||
|  |  | ||||||
| #include "upgrade.h" | #include "upgrade.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,9 +40,11 @@ | |||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "core/logger.h" | #include "base/logger.h" | ||||||
| #include "core/utils/fs.h" | #include "base/utils/fs.h" | ||||||
| #include "core/utils/misc.h" | #include "base/utils/misc.h" | ||||||
|  | #include "base/utils/string.h" | ||||||
|  | #include "base/qinisettings.h" | ||||||
|  |  | ||||||
| bool userAcceptsUpgrade() | bool userAcceptsUpgrade() | ||||||
| { | { | ||||||
| @@ -73,7 +75,7 @@ bool userAcceptsUpgrade() | |||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool upgradeResumeFile(const QString &filepath) | bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent, int &maxPrio) | ||||||
| { | { | ||||||
|     QFile file1(filepath); |     QFile file1(filepath); | ||||||
|     if (!file1.open(QIODevice::ReadOnly)) |     if (!file1.open(QIODevice::ReadOnly)) | ||||||
| @@ -91,6 +93,12 @@ bool upgradeResumeFile(const QString &filepath) | |||||||
|     fastNew = fastOld; |     fastNew = fastOld; | ||||||
|  |  | ||||||
|     int priority = fastOld.dict_find_int_value("qBt-queuePosition"); |     int priority = fastOld.dict_find_int_value("qBt-queuePosition"); | ||||||
|  |     if (priority > maxPrio) | ||||||
|  |         maxPrio = priority; | ||||||
|  |  | ||||||
|  |     fastNew["qBt-name"] = Utils::String::toStdString(oldTorrent.value("name").toString()); | ||||||
|  |     fastNew["qBt-tempPathDisabled"] = false; | ||||||
|  |  | ||||||
|     QFile file2(QString("%1.%2").arg(filepath).arg(priority > 0 ? priority : 0)); |     QFile file2(QString("%1.%2").arg(filepath).arg(priority > 0 ? priority : 0)); | ||||||
|     QVector<char> out; |     QVector<char> out; | ||||||
|     libtorrent::bencode(std::back_inserter(out), fastNew); |     libtorrent::bencode(std::back_inserter(out), fastNew); | ||||||
| @@ -106,26 +114,63 @@ bool upgradeResumeFile(const QString &filepath) | |||||||
|  |  | ||||||
| bool upgrade(bool ask = true) | bool upgrade(bool ask = true) | ||||||
| { | { | ||||||
|  |     QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume"); | ||||||
|  |     QString oldResumeFilename = oldResumeSettings->fileName(); | ||||||
|  |     QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash(); | ||||||
|  |     delete oldResumeSettings; | ||||||
|  |     if (oldResumeData.isEmpty()) | ||||||
|  |         Utils::Fs::forceRemove(oldResumeFilename); | ||||||
|  |  | ||||||
|  |  | ||||||
|     QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup"); |     QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup"); | ||||||
|     QDir backupFolderDir(backupFolderPath); |     QDir backupFolderDir(backupFolderPath); | ||||||
|     if (!backupFolderDir.exists()) return true; |  | ||||||
|  |  | ||||||
|     QStringList backupFiles = backupFolderDir.entryList(QStringList() << QLatin1String("*.fastresume"), QDir::Files, QDir::Unsorted); |     QStringList backupFiles = backupFolderDir.entryList(QStringList() << QLatin1String("*.fastresume"), QDir::Files, QDir::Unsorted); | ||||||
|     if (!backupFiles.isEmpty()) { |     if (backupFiles.isEmpty() && oldResumeData.isEmpty()) return true; | ||||||
|         if (ask && !userAcceptsUpgrade()) return false; |     if (ask && !userAcceptsUpgrade()) return false; | ||||||
|  |  | ||||||
|         QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); |     int maxPrio = 0; | ||||||
|         foreach (QString backupFile, backupFiles) { |     QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); | ||||||
|             if (rx.indexIn(backupFile) != -1) { |     foreach (QString backupFile, backupFiles) { | ||||||
|                 if (!upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile))) |         if (rx.indexIn(backupFile) != -1) { | ||||||
|                     Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING); |             if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash(), maxPrio)) | ||||||
|             } |                 oldResumeData.remove(rx.cap(1)); | ||||||
|             else { |             else | ||||||
|                 Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING); |                 Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING); | ||||||
|             } |         } | ||||||
|  |         else { | ||||||
|  |             Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     foreach (const QString &hash, oldResumeData.keys()) { | ||||||
|  |         QVariantHash oldTorrent = oldResumeData[hash].toHash(); | ||||||
|  |         if (oldTorrent.value("is_magnet", false).toBool()) { | ||||||
|  |             libtorrent::entry resumeData; | ||||||
|  |             resumeData["qBt-magnetUri"] = Utils::String::toStdString(oldTorrent.value("magnet_uri").toString()); | ||||||
|  |             resumeData["qBt-paused"] = false; | ||||||
|  |             resumeData["qBt-forced"] = false; | ||||||
|  |  | ||||||
|  |             resumeData["qBt-savePath"] = Utils::String::toStdString(oldTorrent.value("save_path").toString()); | ||||||
|  |             resumeData["qBt-ratioLimit"] = Utils::String::toStdString(QString::number(oldTorrent.value("max_ratio", -2).toReal())); | ||||||
|  |             resumeData["qBt-label"] = Utils::String::toStdString(oldTorrent.value("label").toString()); | ||||||
|  |             resumeData["qBt-name"] = Utils::String::toStdString(oldTorrent.value("name").toString()); | ||||||
|  |             resumeData["qBt-seedStatus"] = oldTorrent.value("seed").toBool(); | ||||||
|  |             resumeData["qBt-tempPathDisabled"] = false; | ||||||
|  |  | ||||||
|  |             QString filename = QString("%1.fastresume.%2").arg(hash).arg(++maxPrio); | ||||||
|  |             QString filepath = backupFolderDir.absoluteFilePath(filename); | ||||||
|  |  | ||||||
|  |             QFile resumeFile(filepath); | ||||||
|  |             QVector<char> out; | ||||||
|  |             libtorrent::bencode(std::back_inserter(out), resumeData); | ||||||
|  |             if (resumeFile.open(QIODevice::WriteOnly)) | ||||||
|  |                 resumeFile.write(&out[0], out.size()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!oldResumeData.isEmpty()) | ||||||
|  |         QFile(oldResumeFilename).rename(oldResumeFilename + ".bak"); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ | |||||||
| #include <libtorrent/error_code.hpp> | #include <libtorrent/error_code.hpp> | ||||||
| #include <libtorrent/magnet_uri.hpp> | #include <libtorrent/magnet_uri.hpp> | ||||||
|  |  | ||||||
| #include "core/utils/string.h" | #include "base/utils/string.h" | ||||||
| #include "magneturi.h" | #include "magneturi.h" | ||||||
|  |  | ||||||
| namespace libt = libtorrent; | namespace libt = libtorrent; | ||||||
| @@ -26,9 +26,10 @@ | |||||||
|  * exception statement from your version. |  * exception statement from your version. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "core/net/geoipmanager.h" | #include "base/net/geoipmanager.h" | ||||||
| #include "core/utils/string.h" | #include "base/utils/string.h" | ||||||
| #include "core/unicodestrings.h" | #include "base/unicodestrings.h" | ||||||
|  | #include "base/bittorrent/torrenthandle.h" | ||||||
| #include "peerinfo.h" | #include "peerinfo.h" | ||||||
|  |  | ||||||
| namespace libt = libtorrent; | namespace libt = libtorrent; | ||||||
| @@ -49,9 +50,11 @@ PeerAddress::PeerAddress(QHostAddress ip, ushort port) | |||||||
|  |  | ||||||
| // PeerInfo | // PeerInfo | ||||||
|  |  | ||||||
| PeerInfo::PeerInfo(const libt::peer_info &nativeInfo) | PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeInfo) | ||||||
|     : m_nativeInfo(nativeInfo) |     : m_nativeInfo(nativeInfo) | ||||||
| { | { | ||||||
|  |     calcRelevance(torrent); | ||||||
|  |     determineFlags(); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool PeerInfo::fromDHT() const | bool PeerInfo::fromDHT() const | ||||||
| @@ -253,3 +256,155 @@ QString PeerInfo::connectionType() const | |||||||
|  |  | ||||||
|     return connection; |     return connection; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void PeerInfo::calcRelevance(const TorrentHandle *torrent) | ||||||
|  | { | ||||||
|  |     const QBitArray &allPieces = torrent->pieces(); | ||||||
|  |     const QBitArray &peerPieces = pieces(); | ||||||
|  |  | ||||||
|  |     int localMissing = 0; | ||||||
|  |     int remoteHaves = 0; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < allPieces.size(); ++i) { | ||||||
|  |         if (!allPieces[i]) { | ||||||
|  |             ++localMissing; | ||||||
|  |             if (peerPieces[i]) | ||||||
|  |                 ++remoteHaves; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (localMissing == 0) | ||||||
|  |         m_relevance = 0.0; | ||||||
|  |     else | ||||||
|  |         m_relevance = static_cast<qreal>(remoteHaves) / localMissing; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | qreal PeerInfo::relevance() const | ||||||
|  | { | ||||||
|  |     return m_relevance; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void PeerInfo::determineFlags() | ||||||
|  | { | ||||||
|  |     if (isInteresting()) { | ||||||
|  |         //d = Your client wants to download, but peer doesn't want to send (interested and choked) | ||||||
|  |         if (isRemoteChocked()) { | ||||||
|  |             m_flags += "d "; | ||||||
|  |             m_flagsDescription += tr("interested(local) and choked(peer)"); | ||||||
|  |             m_flagsDescription += ", "; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             //D = Currently downloading (interested and not choked) | ||||||
|  |             m_flags += "D "; | ||||||
|  |             m_flagsDescription += tr("interested(local) and unchoked(peer)"); | ||||||
|  |             m_flagsDescription += ", "; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (isRemoteInterested()) { | ||||||
|  |         //u = Peer wants your client to upload, but your client doesn't want to (interested and choked) | ||||||
|  |         if (isChocked()) { | ||||||
|  |             m_flags += "u "; | ||||||
|  |             m_flagsDescription += tr("interested(peer) and choked(local)"); | ||||||
|  |             m_flagsDescription += ", "; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             //U = Currently uploading (interested and not choked) | ||||||
|  |             m_flags += "U "; | ||||||
|  |             m_flagsDescription += tr("interested(peer) and unchoked(local)"); | ||||||
|  |             m_flagsDescription += ", "; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //O = Optimistic unchoke | ||||||
|  |     if (optimisticUnchoke()) { | ||||||
|  |         m_flags += "O "; | ||||||
|  |         m_flagsDescription += tr("optimistic unchoke"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //S = Peer is snubbed | ||||||
|  |     if (isSnubbed()) { | ||||||
|  |         m_flags += "S "; | ||||||
|  |         m_flagsDescription += tr("peer snubbed"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //I = Peer is an incoming connection | ||||||
|  |     if (!isLocalConnection()) { | ||||||
|  |         m_flags += "I "; | ||||||
|  |         m_flagsDescription += tr("incoming connection"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //K = Peer is unchoking your client, but your client is not interested | ||||||
|  |     if (!isRemoteChocked() && !isInteresting()) { | ||||||
|  |         m_flags += "K "; | ||||||
|  |         m_flagsDescription += tr("not interested(local) and unchoked(peer)"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //? = Your client unchoked the peer but the peer is not interested | ||||||
|  |     if (!isChocked() && !isRemoteInterested()) { | ||||||
|  |         m_flags += "? "; | ||||||
|  |         m_flagsDescription += tr("not interested(peer) and unchoked(local)"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //X = Peer was included in peerlists obtained through Peer Exchange (PEX) | ||||||
|  |     if (fromPeX()) { | ||||||
|  |         m_flags += "X "; | ||||||
|  |         m_flagsDescription += tr("peer from PEX"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //H = Peer was obtained through DHT | ||||||
|  |     if (fromDHT()) { | ||||||
|  |         m_flags += "H "; | ||||||
|  |         m_flagsDescription += tr("peer from DHT"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //E = Peer is using Protocol Encryption (all traffic) | ||||||
|  |     if (isRC4Encrypted()) { | ||||||
|  |         m_flags += "E "; | ||||||
|  |         m_flagsDescription += tr("encrypted traffic"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //e = Peer is using Protocol Encryption (handshake) | ||||||
|  |     if (isPlaintextEncrypted()) { | ||||||
|  |         m_flags += "e "; | ||||||
|  |         m_flagsDescription += tr("encrypted handshake"); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //P = Peer is using uTorrent uTP | ||||||
|  |  | ||||||
|  |     if (useUTPSocket()) { | ||||||
|  |         m_flags += "P "; | ||||||
|  |         m_flagsDescription += QString::fromUtf8(C_UTP); | ||||||
|  |         m_flagsDescription += ", "; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //L = Peer is local | ||||||
|  |     if (fromLSD()) { | ||||||
|  |         m_flags += "L"; | ||||||
|  |         m_flagsDescription += tr("peer from LSD"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     m_flags = m_flags.trimmed(); | ||||||
|  |     m_flagsDescription = m_flagsDescription.trimmed(); | ||||||
|  |     if (m_flagsDescription.endsWith(',', Qt::CaseInsensitive)) | ||||||
|  |         m_flagsDescription.chop(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QString PeerInfo::flags() const | ||||||
|  | { | ||||||
|  |     return m_flags; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QString PeerInfo::flagsDescription() const | ||||||
|  | { | ||||||
|  |     return m_flagsDescription; | ||||||
|  | } | ||||||
| @@ -33,9 +33,12 @@ | |||||||
|  |  | ||||||
| #include <QHostAddress> | #include <QHostAddress> | ||||||
| #include <QBitArray> | #include <QBitArray> | ||||||
|  | #include <QCoreApplication> | ||||||
|  |  | ||||||
| namespace BitTorrent | namespace BitTorrent | ||||||
| { | { | ||||||
|  |     class TorrentHandle; | ||||||
|  |  | ||||||
|     struct PeerAddress |     struct PeerAddress | ||||||
|     { |     { | ||||||
|         QHostAddress ip; |         QHostAddress ip; | ||||||
| @@ -47,8 +50,10 @@ namespace BitTorrent | |||||||
|  |  | ||||||
|     class PeerInfo |     class PeerInfo | ||||||
|     { |     { | ||||||
|  |         Q_DECLARE_TR_FUNCTIONS(PeerInfo) | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         PeerInfo(const libtorrent::peer_info &nativeInfo); |         PeerInfo(const TorrentHandle *torrent, const libtorrent::peer_info &nativeInfo); | ||||||
|  |  | ||||||
|         bool fromDHT() const; |         bool fromDHT() const; | ||||||
|         bool fromPeX() const; |         bool fromPeX() const; | ||||||
| @@ -89,12 +94,21 @@ namespace BitTorrent | |||||||
|         qlonglong totalDownload() const; |         qlonglong totalDownload() const; | ||||||
|         QBitArray pieces() const; |         QBitArray pieces() const; | ||||||
|         QString connectionType() const; |         QString connectionType() const; | ||||||
|  |         qreal relevance() const; | ||||||
|  |         QString flags() const; | ||||||
|  |         QString flagsDescription() const; | ||||||
| #ifndef DISABLE_COUNTRIES_RESOLUTION | #ifndef DISABLE_COUNTRIES_RESOLUTION | ||||||
|         QString country() const; |         QString country() const; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |         void calcRelevance(const TorrentHandle *torrent); | ||||||
|  |         void determineFlags(); | ||||||
|  |  | ||||||
|         libtorrent::peer_info m_nativeInfo; |         libtorrent::peer_info m_nativeInfo; | ||||||
|  |         qreal m_relevance; | ||||||
|  |         QString m_flags; | ||||||
|  |         QString m_flagsDescription; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -31,7 +31,7 @@ | |||||||
| #include <QTime> | #include <QTime> | ||||||
| #include <QDateTime> | #include <QDateTime> | ||||||
|  |  | ||||||
| #include "core/preferences.h" | #include "base/preferences.h" | ||||||
| #include "bandwidthscheduler.h" | #include "bandwidthscheduler.h" | ||||||
|  |  | ||||||
| BandwidthScheduler::BandwidthScheduler(QObject *parent) | BandwidthScheduler::BandwidthScheduler(QObject *parent) | ||||||
| @@ -36,7 +36,7 @@ | |||||||
| #include <libtorrent/session.hpp> | #include <libtorrent/session.hpp> | ||||||
| #include <libtorrent/ip_filter.hpp> | #include <libtorrent/ip_filter.hpp> | ||||||
|  |  | ||||||
| #include "core/logger.h" | #include "base/logger.h" | ||||||
| #include "filterparserthread.h" | #include "filterparserthread.h" | ||||||
|  |  | ||||||
| namespace libt = libtorrent; | namespace libt = libtorrent; | ||||||
| @@ -2,10 +2,10 @@ | |||||||
|  |  | ||||||
| #include <libtorrent/session.hpp> | #include <libtorrent/session.hpp> | ||||||
|  |  | ||||||
| #include "core/qinisettings.h" | #include "base/qinisettings.h" | ||||||
| #include "core/preferences.h" | #include "base/preferences.h" | ||||||
| #include "core/bittorrent/sessionstatus.h" | #include "base/bittorrent/sessionstatus.h" | ||||||
| #include "core/bittorrent/session.h" | #include "base/bittorrent/session.h" | ||||||
| #include "statistics.h" | #include "statistics.h" | ||||||
|  |  | ||||||
| static const qint64 SAVE_INTERVAL = 15 * 60 * 1000; | static const qint64 SAVE_INTERVAL = 15 * 60 * 1000; | ||||||
| @@ -83,7 +83,7 @@ void Statistics::load() | |||||||
|     // Don't forget to remove: |     // Don't forget to remove: | ||||||
|     // 1. Preferences::getStats() |     // 1. Preferences::getStats() | ||||||
|     // 2. Preferences::removeStats() |     // 2. Preferences::removeStats() | ||||||
|     // 3. #include "core/preferences.h" |     // 3. #include "base/preferences.h" | ||||||
|     Preferences* const pref = Preferences::instance(); |     Preferences* const pref = Preferences::instance(); | ||||||
|     QIniSettings s("qBittorrent", "qBittorrent-data"); |     QIniSettings s("qBittorrent", "qBittorrent-data"); | ||||||
|     QVariantHash v = pref->getStats(); |     QVariantHash v = pref->getStats(); | ||||||
| @@ -63,20 +63,20 @@ using namespace BitTorrent; | |||||||
| //#include <libtorrent/extensions/metadata_transfer.hpp> | //#include <libtorrent/extensions/metadata_transfer.hpp> | ||||||
|  |  | ||||||
| #ifndef DISABLE_COUNTRIES_RESOLUTION | #ifndef DISABLE_COUNTRIES_RESOLUTION | ||||||
| #include "core/net/geoipmanager.h" | #include "base/net/geoipmanager.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "core/utils/misc.h" | #include "base/utils/misc.h" | ||||||
| #include "core/utils/fs.h" | #include "base/utils/fs.h" | ||||||
| #include "core/utils/string.h" | #include "base/utils/string.h" | ||||||
| #include "core/unicodestrings.h" | #include "base/unicodestrings.h" | ||||||
| #include "core/logger.h" | #include "base/logger.h" | ||||||
| #include "core/preferences.h" | #include "base/preferences.h" | ||||||
| #include "core/torrentfilter.h" | #include "base/torrentfilter.h" | ||||||
| #include "core/net/downloadmanager.h" | #include "base/net/downloadmanager.h" | ||||||
| #include "core/net/downloadhandler.h" | #include "base/net/downloadhandler.h" | ||||||
| #include "core/net/portforwarder.h" | #include "base/net/portforwarder.h" | ||||||
| #include "core/utils/string.h" | #include "base/utils/string.h" | ||||||
| #include "private/filterparserthread.h" | #include "private/filterparserthread.h" | ||||||
| #include "private/statistics.h" | #include "private/statistics.h" | ||||||
| #include "private/bandwidthscheduler.h" | #include "private/bandwidthscheduler.h" | ||||||
| @@ -466,7 +466,8 @@ void Session::configure() | |||||||
|         m_torrentExportEnabled = torrentExportEnabled; |         m_torrentExportEnabled = torrentExportEnabled; | ||||||
|         if (m_torrentExportEnabled) { |         if (m_torrentExportEnabled) { | ||||||
|             qDebug("Torrent export is enabled, exporting the current torrents"); |             qDebug("Torrent export is enabled, exporting the current torrents"); | ||||||
|             exportTorrentFiles(pref->getTorrentExportDir()); |             for (auto torrent: m_torrents) | ||||||
|  |                 exportTorrentFile(torrent); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1151,57 +1152,22 @@ void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolde | |||||||
|     Q_ASSERT(((folder == TorrentExportFolder::Regular) && m_torrentExportEnabled) || |     Q_ASSERT(((folder == TorrentExportFolder::Regular) && m_torrentExportEnabled) || | ||||||
|              ((folder == TorrentExportFolder::Finished) && m_finishedTorrentExportEnabled)); |              ((folder == TorrentExportFolder::Finished) && m_finishedTorrentExportEnabled)); | ||||||
|  |  | ||||||
|  |     QString validName = Utils::Fs::toValidFileSystemName(torrent->name()); | ||||||
|     QString torrentFilename = QString("%1.torrent").arg(torrent->hash()); |     QString torrentFilename = QString("%1.torrent").arg(torrent->hash()); | ||||||
|  |     QString torrentExportFilename = QString("%1.torrent").arg(validName); | ||||||
|     QString torrentPath = QDir(m_resumeFolderPath).absoluteFilePath(torrentFilename); |     QString torrentPath = QDir(m_resumeFolderPath).absoluteFilePath(torrentFilename); | ||||||
|     QDir exportPath(folder == TorrentExportFolder::Regular ? Preferences::instance()->getTorrentExportDir() : Preferences::instance()->getFinishedTorrentExportDir()); |     QDir exportPath(folder == TorrentExportFolder::Regular ? Preferences::instance()->getTorrentExportDir() : Preferences::instance()->getFinishedTorrentExportDir()); | ||||||
|     if (exportPath.exists() || exportPath.mkpath(exportPath.absolutePath())) { |     if (exportPath.exists() || exportPath.mkpath(exportPath.absolutePath())) { | ||||||
|         QString newTorrentPath = exportPath.absoluteFilePath(torrentFilename); |         QString newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename); | ||||||
|         if (QFile::exists(newTorrentPath) && Utils::Fs::sameFiles(torrentPath, newTorrentPath)) { |         int counter = 0; | ||||||
|             // Append hash to torrent name to make it unique |         while (QFile::exists(newTorrentPath) && !Utils::Fs::sameFiles(torrentPath, newTorrentPath)) { | ||||||
|             newTorrentPath = exportPath.absoluteFilePath(torrent->name() + "-" + torrentFilename); |             // Append number to torrent name to make it unique | ||||||
|         } |             torrentExportFilename = QString("%1 %2.torrent").arg(validName).arg(++counter); | ||||||
|         QFile::copy(torrentPath, newTorrentPath); |             newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename); | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void Session::exportTorrentFiles(QString path) |  | ||||||
| { |  | ||||||
|     // NOTE: Maybe create files from current metadata here? |  | ||||||
|     Q_ASSERT(m_torrentExportEnabled); |  | ||||||
|  |  | ||||||
|     QDir exportDir(path); |  | ||||||
|     if (!exportDir.exists()) { |  | ||||||
|         if (!exportDir.mkpath(exportDir.absolutePath())) { |  | ||||||
|             Logger::instance()->addMessage(tr("Error: Could not create torrent export directory: '%1'").arg(exportDir.absolutePath()), Log::CRITICAL); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     QDir resumeDataDir(m_resumeFolderPath); |  | ||||||
|     foreach (TorrentHandle *const torrent, m_torrents) { |  | ||||||
|         if (!torrent->isValid()) { |  | ||||||
|             Logger::instance()->addMessage(tr("Torrent Export: torrent is invalid, skipping..."), Log::CRITICAL); |  | ||||||
|             continue; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const QString srcPath(resumeDataDir.absoluteFilePath(QString("%1.torrent").arg(torrent->hash()))); |         if (!QFile::exists(newTorrentPath)) | ||||||
|         if (QFile::exists(srcPath)) { |             QFile::copy(torrentPath, newTorrentPath); | ||||||
|             QString dstPath = exportDir.absoluteFilePath(QString("%1.torrent").arg(torrent->name())); |  | ||||||
|             if (QFile::exists(dstPath)) { |  | ||||||
|                 if (!Utils::Fs::sameFiles(srcPath, dstPath)) { |  | ||||||
|                     dstPath = exportDir.absoluteFilePath(QString("%1-%2.torrent").arg(torrent->name()).arg(torrent->hash())); |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                     qDebug("Torrent Export: Destination file exists, skipping..."); |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             qDebug("Export Torrent: %s -> %s", qPrintable(srcPath), qPrintable(dstPath)); |  | ||||||
|             QFile::copy(srcPath, dstPath); |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             Logger::instance()->addMessage(tr("Error: could not export torrent '%1', maybe it has not metadata yet.").arg(torrent->hash()), Log::CRITICAL); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1433,6 +1399,8 @@ void Session::networkOnlineStateChanged(const bool online) | |||||||
| void Session::networkConfigurationChange(const QNetworkConfiguration& cfg) | void Session::networkConfigurationChange(const QNetworkConfiguration& cfg) | ||||||
| { | { | ||||||
|     const QString configuredInterfaceName = Preferences::instance()->getNetworkInterface(); |     const QString configuredInterfaceName = Preferences::instance()->getNetworkInterface(); | ||||||
|  |     // Empty means "Any Interface". In this case libtorrent has binded to 0.0.0.0 so any change to any interface will | ||||||
|  |     // be automatically picked up. Otherwise we would rebinding here to 0.0.0.0 again. | ||||||
|     if (configuredInterfaceName.isEmpty()) |     if (configuredInterfaceName.isEmpty()) | ||||||
|         return; |         return; | ||||||
|     const QString changedInterface = cfg.name(); |     const QString changedInterface = cfg.name(); | ||||||
| @@ -1511,7 +1479,7 @@ void Session::setListeningPort() | |||||||
|             m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port); |             m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port); | ||||||
|  |  | ||||||
|             if (ec) |             if (ec) | ||||||
|                 logger->addMessage(tr("qBittorrent failed to listen on any interface port: %1. Reason: %2", "e.g: qBittorrent failed to listen on any interface port: TCP/6881. Reason: no such interface" ).arg(QString::number(port)).arg(Utils::String::fromStdString(ec.message())), Log::CRITICAL); |                 logger->addMessage(tr("qBittorrent failed to listen on any interface port: %1. Reason: %2.", "e.g: qBittorrent failed to listen on any interface port: TCP/6881. Reason: no such interface" ).arg(QString::number(port)).arg(QString::fromLocal8Bit(ec.message().c_str())), Log::CRITICAL); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -1996,7 +1964,7 @@ void Session::getPendingAlerts(QVector<libt::alert *> &out, ulong time) | |||||||
|  |  | ||||||
|     QMutexLocker lock(&m_alertsMutex); |     QMutexLocker lock(&m_alertsMutex); | ||||||
|  |  | ||||||
|     while (m_alerts.empty()) |     if (m_alerts.empty()) | ||||||
|         m_alertsWaitCondition.wait(&m_alertsMutex, time); |         m_alertsWaitCondition.wait(&m_alertsMutex, time); | ||||||
|  |  | ||||||
|     m_alerts.swap(out); |     m_alerts.swap(out); | ||||||
| @@ -2304,10 +2272,10 @@ void Session::handleListenFailedAlert(libt::listen_failed_alert *p) | |||||||
|         proto = "SOCKS5"; |         proto = "SOCKS5"; | ||||||
|     qDebug() << "Failed listening on " << proto << p->endpoint.address().to_string(ec).c_str() << "/" << p->endpoint.port(); |     qDebug() << "Failed listening on " << proto << p->endpoint.address().to_string(ec).c_str() << "/" << p->endpoint.port(); | ||||||
|     Logger::instance()->addMessage( |     Logger::instance()->addMessage( | ||||||
|                 tr("qBittorrent failed listening on interface %1 port: %2/%3. Reason: %4", |                 tr("qBittorrent failed listening on interface %1 port: %2/%3. Reason: %4.", | ||||||
|                    "e.g: qBittorrent failed listening on interface 192.168.0.1 port: TCP/6881. Reason: already in use") |                    "e.g: qBittorrent failed listening on interface 192.168.0.1 port: TCP/6881. Reason: already in use") | ||||||
|                 .arg(p->endpoint.address().to_string(ec).c_str()).arg(proto).arg(QString::number(p->endpoint.port())) |                 .arg(p->endpoint.address().to_string(ec).c_str()).arg(proto).arg(QString::number(p->endpoint.port())) | ||||||
|                 .arg(Utils::String::fromStdString(p->error.message())), Log::CRITICAL); |                 .arg(QString::fromLocal8Bit(p->error.message().c_str())), Log::CRITICAL); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Session::handleExternalIPAlert(libt::external_ip_alert *p) | void Session::handleExternalIPAlert(libt::external_ip_alert *p) | ||||||
| @@ -38,8 +38,8 @@ | |||||||
| #include <QWaitCondition> | #include <QWaitCondition> | ||||||
| #include <QNetworkConfigurationManager> | #include <QNetworkConfigurationManager> | ||||||
|  |  | ||||||
| #include "core/tristatebool.h" | #include "base/tristatebool.h" | ||||||
| #include "core/types.h" | #include "base/types.h" | ||||||
| #include "torrentinfo.h" | #include "torrentinfo.h" | ||||||
|  |  | ||||||
| namespace libtorrent | namespace libtorrent | ||||||
| @@ -293,7 +293,6 @@ namespace BitTorrent | |||||||
|  |  | ||||||
|         void updateRatioTimer(); |         void updateRatioTimer(); | ||||||
|         void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular); |         void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular); | ||||||
|         void exportTorrentFiles(QString path); |  | ||||||
|         void saveTorrentResumeData(TorrentHandle *const torrent); |         void saveTorrentResumeData(TorrentHandle *const torrent); | ||||||
|  |  | ||||||
|         void handleAlert(libtorrent::alert *a); |         void handleAlert(libtorrent::alert *a); | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user