Compare commits
127 Commits
release-3.
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfcc29e25a | ||
|
|
09e2dd15e2 | ||
|
|
49fd36aa2c | ||
|
|
f9064d8b00 | ||
|
|
01df76915c | ||
|
|
52f6b008f4 | ||
|
|
abeed2c6f0 | ||
|
|
01fcf82b0c | ||
|
|
92c70bc878 | ||
|
|
1c313c7c06 | ||
|
|
ed4ca7b769 | ||
|
|
795a3a01c2 | ||
|
|
f31f067bbf | ||
|
|
10905eb04b | ||
|
|
8637996a99 | ||
|
|
39867f4681 | ||
|
|
30659a353d | ||
|
|
d4b5f68295 | ||
|
|
01725b1b55 | ||
|
|
64654705ca | ||
|
|
049b08999a | ||
|
|
0150a05c68 | ||
|
|
8df71e6c44 | ||
|
|
cc53b5bb15 | ||
|
|
e66a956596 | ||
|
|
799a6f0d85 | ||
|
|
5d4a660631 | ||
|
|
a721fd389b | ||
|
|
5923be57b4 | ||
|
|
1a9bd1b171 | ||
|
|
4322d38b87 | ||
|
|
f16a7e0088 | ||
|
|
9a24243359 | ||
|
|
b5e2058b44 | ||
|
|
ddc803a250 | ||
|
|
1fd63f0665 | ||
|
|
2b1399303e | ||
|
|
82e7a2d724 | ||
|
|
0dc8773595 | ||
|
|
1d358dc9a7 | ||
|
|
1fc0310803 | ||
|
|
3b35050736 | ||
|
|
adfdb78821 | ||
|
|
c3e79b843b | ||
|
|
ee83c5490e | ||
|
|
9ccf603c0b | ||
|
|
ae8d92f7d0 | ||
|
|
095c8654e8 | ||
|
|
fae47c8494 | ||
|
|
65efd657a0 | ||
|
|
552bc3c689 | ||
|
|
8d563f9eb6 | ||
|
|
54cd79201f | ||
|
|
9c633b0975 | ||
|
|
67db694494 | ||
|
|
a42d4afeb7 | ||
|
|
a8a42fb8f3 | ||
|
|
2b9692ddde | ||
|
|
4b3c04439e | ||
|
|
f0a2efd481 | ||
|
|
2a44ec9b91 | ||
|
|
895d5151e1 | ||
|
|
233d6bbb8d | ||
|
|
66ee39df9a | ||
|
|
35e36036be | ||
|
|
1b0de21b52 | ||
|
|
536f275ca3 | ||
|
|
3238336e6e | ||
|
|
bd8c03ecd8 | ||
|
|
32ed944ac8 | ||
|
|
72fbf11f70 | ||
|
|
0dc4b27cb6 | ||
|
|
a5aa1a5cab | ||
|
|
2dbf418f5a | ||
|
|
04f6d96575 | ||
|
|
25eb43d3bb | ||
|
|
cc785c4eea | ||
|
|
a589cb7fdc | ||
|
|
4704b50379 | ||
|
|
f43de35c33 | ||
|
|
ec61870c9e | ||
|
|
746ffaf420 | ||
|
|
c60545977c | ||
|
|
10020ed520 | ||
|
|
0aae5f947d | ||
|
|
11b5965b31 | ||
|
|
35b2377e68 | ||
|
|
b0ab072aba | ||
|
|
4552df5ec2 | ||
|
|
c19db4fa04 | ||
|
|
74e2339bc8 | ||
|
|
991c308423 | ||
|
|
1867643288 | ||
|
|
50023bd968 | ||
|
|
30c5bf3fd6 | ||
|
|
4e2d9564d1 | ||
|
|
600186a6e9 | ||
|
|
ca0e605276 | ||
|
|
201aaae897 | ||
|
|
629dc15bef | ||
|
|
35541e14aa | ||
|
|
cdede2d3db | ||
|
|
1f2e34b828 | ||
|
|
d5aaf975dd | ||
|
|
4ac59dbaba | ||
|
|
67802b16ab | ||
|
|
41883c99c5 | ||
|
|
d663c7bd3a | ||
|
|
a6d1090515 | ||
|
|
7844ce287d | ||
|
|
c6ce0d35b2 | ||
|
|
eec56074fc | ||
|
|
7c180dc57a | ||
|
|
043b9f2981 | ||
|
|
229559ef67 | ||
|
|
5e4b815d0f | ||
|
|
c98ab55e11 | ||
|
|
632c2c5e4a | ||
|
|
bbd9764f9c | ||
|
|
7437bd4265 | ||
|
|
1299e75934 | ||
|
|
514f82a3c9 | ||
|
|
51a69dc36a | ||
|
|
737fee79ed | ||
|
|
e5e4bb1111 | ||
|
|
75111cdd8a | ||
|
|
f5f915eb5d |
15
.gitignore
vendored
@@ -1,15 +0,0 @@
|
||||
src/geoip/GeoIP.dat
|
||||
src/qbittorrent
|
||||
qbittorrent.pro.user*
|
||||
conf.pri
|
||||
Makefile
|
||||
*.pyc
|
||||
*.log
|
||||
# Compiled object files
|
||||
*.o
|
||||
# Generated MOC, resource and UI files
|
||||
moc_*.cpp
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
*.moc
|
||||
src/lang/qbittorrent_*.qm
|
||||
53
.travis.yml
@@ -1,53 +0,0 @@
|
||||
language:
|
||||
- cpp
|
||||
|
||||
env:
|
||||
# use libtorrent 0.15.10
|
||||
- lt_source=from_dist gui=true
|
||||
- lt_source=from_dist gui=false
|
||||
# use libtorrent 0.16.X from RC_0_16 svn branch
|
||||
- lt_source=from_svn gui=true
|
||||
- lt_source=from_svn gui=false
|
||||
|
||||
branches:
|
||||
except:
|
||||
- search_encoding_windows
|
||||
- v2_9_x
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
|
||||
before_install:
|
||||
- shopt -s expand_aliases
|
||||
- alias sudo="sudo "
|
||||
# Using nprocs/2 sometimes may fail (gcc is killed by system), just use two threads
|
||||
- alias make="colormake -j2 "
|
||||
|
||||
# Also setup a virtual display for after_success target when gui == true
|
||||
- if ! $gui; then qbtconf="$qbtconf --disable-gui"; else export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi
|
||||
- ltconf=" --with-libgeoip=system"
|
||||
|
||||
- echo settings
|
||||
- echo $lt_source
|
||||
- echo $ltconf
|
||||
- echo $gui
|
||||
- echo $qbtconf
|
||||
|
||||
- sudo apt-get -qq update
|
||||
# Travis can stall during heavy load if these packages are installed in one step - split the command
|
||||
- sudo apt-get -qq install debhelper qconf colormake libssl-dev libgeoip-dev
|
||||
- sudo apt-get -qq install libboost-dev libboost-filesystem-dev libboost-system-dev
|
||||
- sudo apt-get -qq install libqt4-dev
|
||||
|
||||
install:
|
||||
- if [[ "$lt_source" == "from_dist" ]]; then sudo apt-get -qq install libtorrent-rasterbar-dev; fi
|
||||
- if [[ "$lt_source" == "from_svn" ]]; then cd .. && svn co svn://svn.code.sf.net/p/libtorrent/code/branches/RC_0_16 ./libtorrent && (cd libtorrent && ./autotool.sh && ./configure $ltconf && sudo make install) && sudo ldconfig /usr/local/lib && cd $TRAVIS_BUILD_DIR ; fi
|
||||
|
||||
script:
|
||||
- qt-qconf
|
||||
- ./configure $qbtconf && sudo make install
|
||||
|
||||
after_success:
|
||||
- if $gui ; then qbittorrent --version ; else qbittorrent-nox --version ; fi
|
||||
18
.tx/config
@@ -1,18 +0,0 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[qbittorrent.qbittorrent_v3_1_x]
|
||||
file_filter = src/lang/qbittorrent_<lang>.ts
|
||||
source_file = src/lang/qbittorrent_en.ts
|
||||
source_lang = en
|
||||
type = QT
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
|
||||
|
||||
[qbittorrent.qbittorrentdesktop_master]
|
||||
source_file = src/Icons/qBittorrent.desktop
|
||||
source_lang = en
|
||||
type = DESKTOP
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
52
AUTHORS
@@ -1,7 +1,4 @@
|
||||
Current maintainer:
|
||||
* Sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||
|
||||
Original author:
|
||||
Author:
|
||||
* Christophe Dumez <chris@qbittorrent.org>
|
||||
|
||||
Contributors:
|
||||
@@ -14,7 +11,6 @@ Contributors:
|
||||
* Grigis Gaëtan <cipher16@gmail.com>
|
||||
* Christian Kandeler <zambesi@users.sourceforge.net>
|
||||
* Silvan Scherrer <silvan.scherrer@aroa.ch>
|
||||
* Nick Tiskov <daymansmail@gmail.com>
|
||||
|
||||
Code from other projects:
|
||||
* files src/qtsingleapp/* src/lineedit/*
|
||||
@@ -29,10 +25,6 @@ Code from other projects:
|
||||
copyright: Dan Haim <negativeiq@users.sourceforge.net>
|
||||
license: BSD
|
||||
|
||||
* file src/stacktrace_win.h
|
||||
copyright: Quassel Project
|
||||
license: GPLv2/3
|
||||
|
||||
Images Authors:
|
||||
* files: src/Icons/*.png
|
||||
copyright: Gnome Icon Theme
|
||||
@@ -58,10 +50,6 @@ Images Authors:
|
||||
copyright: Greg Houston <gregory.houston@gmail.com>
|
||||
license: MIT
|
||||
|
||||
* file: src/Icons/skin/qbittorrent_mono*
|
||||
copyright: Daniel Eguren <deguren@gmail.com>
|
||||
license: LGPL
|
||||
|
||||
* file: src/search_engine/engines/btjunkie.png
|
||||
copyright: Downloaded from btjunkie.org
|
||||
|
||||
@@ -79,46 +67,38 @@ Images Authors:
|
||||
|
||||
Translations authors:
|
||||
* files: src/lang/*.ts
|
||||
* file: src/Icons/qBittorrent.desktop
|
||||
copyright:
|
||||
- Arabic: SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)
|
||||
- Arabic: SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)
|
||||
- Armenian: Hrant Ohanyan (hrantohanyan@mail.am)
|
||||
- Basque: Xabier Aramendi (azpidatziak@gmail.com)
|
||||
- Belarusian: Mihas Varantsou (meequz@gmail.com)
|
||||
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
|
||||
- Bulgarian: Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)
|
||||
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
|
||||
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
|
||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com) and 冥王歐西里斯 s8321414(Transifex)
|
||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
|
||||
- Croatian: Oliver Mucafir (oliver.untwist@gmail.com)
|
||||
- Czech: Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex)
|
||||
- Czech: Jirka Vilim (web@tets.cz)
|
||||
- Danish: Mathias Nielsen (comoneo@gmail.com)
|
||||
- Dutch: Pieter Heyvaert (pieter_heyvaert@hotmail.com)
|
||||
- English: Christophe Dumez (chris@qbittorrent.org)
|
||||
- English(Australia): Robert Readman readmanr(Transifex)
|
||||
- English(United Kingdom): Robert Readman readmanr(Transifex)
|
||||
- Finnish: Niklas Laxström (nikerabbit@users.sourceforge.net), Pekka Niemi (pekka.niemi@iki.fi) and Jiri Grönroos artnay(Transifex)
|
||||
- Finnish: Niklas Laxström (nikerabbit@users.sourceforge.net)
|
||||
- French: Christophe Dumez (chris@qbittorrent.org)
|
||||
- Galician: Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex)
|
||||
- Georgian: Beqa Arabuli (arabulibeqa@yahoo.com)
|
||||
- Galician: Marcos Lans (marcoslansgarza@gmail.com)
|
||||
- German: Niels Hoffmann (zentralmaschine@users.sourceforge.net)
|
||||
- Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net), Stephanos Antaris (santaris@csd.auth.gr), sledgehammer999(hammered999@gmail.com) and Γιάννης Ανθυμίδης Evropi(Transifex)
|
||||
- Hebrew: David Deutsch (d.deffo@gmail.com)
|
||||
- Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net) and Stephanos Antaris (santaris@csd.auth.gr)
|
||||
- Hungarian: Majoros Péter (majoros.j.p@t-online.hu)
|
||||
- Italian: bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)
|
||||
- Japanese: Masato Hashimoto (cabezon.hashimoto@gmail.com)
|
||||
- Italian: Matteo Sechi (bu17714@gmail.com)
|
||||
- Japanese: Nardog (alphisation@gmail.com)
|
||||
- Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
|
||||
- Lithuanian: Naglis Jonaitis (njonaitis@gmail.com)
|
||||
- Norwegian: Tomaso
|
||||
- Polish: Mariusz Fik (fisiu@opensuse.org)
|
||||
- Portuguese: Sérgio Marques smarquespt(Transifex)
|
||||
- Portuguese(Brazil): Nick Marinho (nickmarinho@gmail.com)
|
||||
- Romanian: Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex)
|
||||
- Russian: Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex)
|
||||
- Portuguese: Nick Marinho (nickmarinho@gmail.com)
|
||||
- Romanian: Obada Denis (obadadenis@users.sourceforge.net)
|
||||
- Russian: Nick Khazov (m2k3d0n at users.sourceforge.net)
|
||||
- Serbian: Anaximandar Milet (anaximandar at operamail.com)
|
||||
- Slovak: helix84
|
||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com), Alfredo Monclus alfrix(Transifex) and José Antonio Moray moray33(Transifex)
|
||||
- Swedish: Daniel Nylander (po@danielnylander.se) and Emil Hammarberg Ooglogput(Transifex)
|
||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
||||
- Swedish: Daniel Nylander (po@danielnylander.se)
|
||||
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
|
||||
- Ukrainian: Oleh Prypin (blaxpirit@gmail.com) and zubr139(Transifex)
|
||||
- Vietnamese: Anh Phan ppanhh(Transifex)
|
||||
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)
|
||||
license: GPLv2
|
||||
|
||||
10
COPYING
@@ -69,7 +69,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -124,7 +124,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -182,7 +182,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -239,7 +239,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -292,7 +292,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
|
||||
343
Changelog
@@ -1,282 +1,83 @@
|
||||
* Sun Sep 21 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.10
|
||||
- FEATURE: Allow disabling of OS cache. This will prevent RAM increases on Windows when seeding many files. Closes #1699. (sledgehammer999)
|
||||
- FEATURE: Add 'Completed' column. Closes #1241. (sledgehammer999)
|
||||
- FEATURE: Added 'Ratio Limit' column. Closes #936. (sledgehammer999)
|
||||
- FEATURE: Add 'Open' and 'Open Containing Folder' entries in the content's right-click menu. Closes #1143. (sledgehammer999)
|
||||
- FEATURE: Don't listen on IPv6 address by default. Prevents network connectivity problems. Closes #1880. (sledgehammer999)
|
||||
- FEATURE: Added 'Shutdown now' button in shutdown confirmation dialog. Closes #969. (sledgehammer999)
|
||||
- FEATURE: Add peer port column to PeerListWidget. Closes #1650. (Ivanov Juriy)
|
||||
- COSMETIC: Fix weird ratio values when torrent was imported or downloaded history was lost due to crash. (sledgehammer999)
|
||||
- COSMETIC: Use 'μTP' instead of 'uTP'. (sledgehammer999)
|
||||
- COSMETIC: Show the loaded torrents in the transferlist when qBT is launched with a torrent/magnet and the AddNewTorrentDialog is showing. Closes #1564. (sledgehammer999)
|
||||
- COSMETIC: Don't mix finished/unifinished torrents when sorting by ETA. Closes #1688. (sledgehammer999)
|
||||
- COSMETIC: Sort finished torrents by completed date when sorting by queue number. (sledgehammer999)
|
||||
- COSMETIC: Right align numerical values in the transfer list. Partially revert 51a9a9aab. Closes #1903. (sledgehammer999)
|
||||
- COSMETIC: Don't display the Search Engine tab by default. (sledgehammer999)
|
||||
- WINDOWS: Correctly associate torrents and magnet links with qBittorrent under non-admin accounts. Closes #291 #527 #579 #614 #964. (glassez, sledgehammer999)
|
||||
- WINDOWS: Check for python before creating the search engine tab. Prevents the creation of python specific files in the user's PC if no python is found. Closes #1370. (sledgehammer999)
|
||||
- WINDOWS: Don't create keys in the registry if python isn't found. Closes #1370. (sledgehammer999)
|
||||
- WINDOWS: Can now correctly detect 64bit and 32bit python installations on 64bit Windows. Closes #1148 #445 #795 #1708. (sledgehammer999)
|
||||
- WINDOWS: Search first in PATH for python. Closes #956. (sledgehammer999)
|
||||
- OSX: Enable system tray in MACOSX (Nick Korotysh).
|
||||
- OSX: Fix headless (nox) build. (sledgehammer999)
|
||||
- WEBUI: Correctly save/load settings and other improvements (glassez)
|
||||
- WEBUI: Removed broken 'Report a bug' iframe. Closes #1343 (Benjamin Hutchins)
|
||||
- WEBUI: Removed broken 'Documentation'. Improves fix for #1343 (Benjamin Hutchins)
|
||||
- WEBUI: Removed essentially useless 'Visit website' iframe and changed it to a regular link. Improves fix for #1343 (Benjamin Hutchins)
|
||||
- BUGFIX: Fix RSS feed icon. The tmp file gets deleted in the feed destructor. Closes #1639 (sledgehammer999)
|
||||
- BUGFIX: fix issue #1674: AddNewTorrentDialog is shown again and again even if checkbox "dont ask me again" is set (Ivan Sorokin)
|
||||
- BUGFIX: Don't show availability bar for magnet links (Ivan Sorokin)
|
||||
- BUGFIX: Fix crash when the selected torrent disappears from the transfer list. Closes #1661 (sledgehammer999)
|
||||
- BUGFIX: Fix tracker announcing problem(hit-and-run) when many torrents are being active. Closes #1571 (sledgehammer999)
|
||||
- BUGFIX: Count magnet links in the 'downloading' filter and make them prevent system inhibition. Closes #1558 (sledgehammer999)
|
||||
- BUGFIX: Pick up updated plugins. Closes #1745. (sledgehammer999)
|
||||
- BUGFIX: Bring mainwindow in front when notification is clicked and other windows are in front. (sledgehammer999)
|
||||
- BUGFIX: Speedup torrent moving (Ivan Sorokin)
|
||||
- BUGFIX: Fix bug when moving a torrent before the previous move is completed (Ivan Sorokin)
|
||||
- BUGFIX: Add option to hibernate computer in Auto-Shutdown menu (Bruno Barbieri)
|
||||
- BUGFIX: Fix column resizing issues (Bryan Roscoe)
|
||||
- BUGFIX: Fix possible crashes. Closes #1814. (sledgehammer999)
|
||||
- BUGFIX: Limit max cache to 1800MiB for 32bits compiled binaries and to 4GiB for other. Closes #1698. (sledgehammer999)
|
||||
- BUGFIX: Don't localize double numbers in the webui. Closes #1525. (sledgehammer999)
|
||||
- BUGFIX: Don't shrink transferlist rows when scrolling horizontally. Closes #1613. (sledgehammer999)
|
||||
- BUGFIX: When qBT is launched with a magnet don't show it in the transferlist while the metadata are being loaded in the background. (sledgehammer999)
|
||||
- BUGFIX: Show disk space while retrieving metadata. Closes #1693. (sledgehammer999)
|
||||
- BUGFIX: Don't disable DHT/LSD/UPnP in the GUI when anonymous mode is enabled. (sledgehammer999)
|
||||
- BUGFIX: Possible fix for crash in RSS code. Closes #1901. (sledgehammer999)
|
||||
- BUGFIX: Fixed SMTP emailing code (Ivanov Juriy, sledgehammer999)
|
||||
- BUGFIX: Don't display the context menu in 'Content' and 'HTTP Sources' buttons when no torrent is selected. It prevents crashes. Closes #1906, #1900. (sledgehammer999)
|
||||
- BUGFIX: Don't translate file extensions. Closes #1907. (sledgehammer999)
|
||||
- BUGFIX: Fix available disk space label on single file torrents. (sledgehammer999)
|
||||
- BUGFIX: Show stalled downloads that are uploading under the 'Active' filter. Closes #1654." (sledgehammer999)
|
||||
- BUGFIX: fix import torrent with "Keep incomplete torrents in:" enabled (lojack5)
|
||||
- BUGFIX: Send a spoofed user agent for the search engines(fixes some of them) (Martin Janco)
|
||||
- BUGFIX: Support URLs that redirect to magnet links (Gelmir)
|
||||
- BUGFIX: Consider queued items before deciding to 'auto-shutdown on downloads completion'. Closes #1942. (sledgehammer999)
|
||||
* Sun Mar 13 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.9
|
||||
- BUGFIX: Fix column hiding/showing in transfer list
|
||||
|
||||
* Tue Apr 29 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.9.2
|
||||
- OTHER: The v3.1.9.1 Windows build was broken
|
||||
* Sun Mar 13 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.8
|
||||
- BUGFIX: Fix compilation with libtorrent v0.14.x
|
||||
- BUGFIX: Fix issues when writing on NTFS (Linux, Mac)
|
||||
- BUGFIX: Fix root folder being cut off if the torrent comes from a scanned folder (Christian Kandeler)
|
||||
- BUGFIX: Improve folder removal behavior
|
||||
- BUGFIX: Make sure the .unwanted folder is deleted on soft torrent removal
|
||||
- BUGFIX: Indicate support for Magnet links in desktop file (Fisiu)
|
||||
- BUGFIX: Do not report torrent being checked as queued
|
||||
- BUGFIX: Improve lists columns state saving
|
||||
|
||||
* Mon Apr 28 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.9.1
|
||||
- OTHER: This is an excuse to produce new builds with an OpenSSL version that isn't affected by the heartbleed bug for Windows and Mac. This bug should only affect the WebUI and only if HTTPS/SSL authentication was enabled.
|
||||
* Sat Feb 26 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.7
|
||||
- BUGFIX: Encoding fixes (Windows)
|
||||
- BUGFIX: Fix "append label to save path" (Windows)
|
||||
- BUGFIX: Disable OS cache for aligned files to reduce memory consumption
|
||||
- BUGFIX: Fix torrent upload from Web UI (Windows)
|
||||
- BUGFIX: Fix cursor problem in torrent addition dialog
|
||||
- BUGFIX: Fix crash when additing an empty tracker URL
|
||||
- BUGFIX: Share ratio can now go over 100
|
||||
- BUGFIX: Fix compilation with boost >= v1.46
|
||||
|
||||
* Sat Mar 01 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.9
|
||||
- BUGFIX: Fix nox build. Closes #1368 (bob23450)
|
||||
- BUGFIX: Fix build with libtorrent 0.15.x (sledgehammer999)
|
||||
- BUGFIX: Fix missing percentage signs. Closes #1392. (sledgehammer999)
|
||||
- BUGFIX: Fix queue sorting order. (alfrix)
|
||||
- BUGFIX: Fix build using qt < 4.7 Closes #1385. (Evgeny Lensky)
|
||||
- BUGFIX: Fix autoupdater. Send our user-agent to sourceforge.net (sledgehammer999)
|
||||
- FEATURE: Add button for links in toolbar (alfrix)
|
||||
* Tue Feb 8 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.6
|
||||
- FEATURE: IP address reported to trackers is now customizable
|
||||
- BUGFIX: Use slashes instead of antislashes in URLs (Windows)
|
||||
- BUGFIX: Fix articles read state reset problem in RSS
|
||||
- BUGFIX: Fix possible path encoding issues on Windows
|
||||
- BUGFIX: Fix downloads from URLs on Windows
|
||||
- I18N: Added Lithuanian translation
|
||||
- COSMETIC: Improve main window layout
|
||||
- COSMETIC: Improve properties buttons style
|
||||
- COSMETIC: Display pieces being downloaded in green instead of yellow
|
||||
- COSMETIC: Improve piece availability bar appearance
|
||||
|
||||
* Sun Feb 02 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.8
|
||||
- BUGFIX: Really fix build of v3.1.6
|
||||
* Thu Feb 3 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.5
|
||||
- BUGFIX: Make sure the progress is not 100% unless the file is complete
|
||||
- BUGFIX: Fix memory leak in HTTP torrent downloader
|
||||
- BUGFIX: Use native file dialogs (by Vladimir Golovnev)
|
||||
- BUGFIX: Fix encoding problem in torrent moving code (by Vladimir Golovnev)
|
||||
- BUGFIX: Performance improvement on ARM
|
||||
- BUGFIX: RSS code rewrite (more cpu/memory efficient)
|
||||
- I18N: Updated Norwegian translation (Tomaso)
|
||||
|
||||
* Sun Feb 02 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.7
|
||||
- BUGFIX: Fix build of v3.1.6
|
||||
* Sun Jan 23 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.4
|
||||
- BUGFIX: Added unicode support to email notification
|
||||
- BUGFIX: Improved compatibility with various SMTP servers
|
||||
- BUGFIX: Fix Labeling in RSS downloader
|
||||
- BUGFIX: Avoid main window flashing on startup (closes #703984)
|
||||
- BUGFIX: Improved hostname resolution code
|
||||
- BUGFIX: Dropped dependency on libboost-thread
|
||||
- BUGFIX: Display legal notice on screen center
|
||||
- BUGFIX: Fix renaming of single-file torrents (by Vladimir Golovnev)
|
||||
- I18N: More dialog buttons are now translated (by Vladimir Golovnev)
|
||||
- I18N: Fix translation of size units (by Vladimir Golovnev)
|
||||
|
||||
* Sun Feb 02 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.6
|
||||
- BUGFIX: Fix 'preview file' regression. Closes #1285. (sledgehammer999)
|
||||
- BUGFIX: Fix peers and seeds sorting in transfer list. (Angel Alonso)
|
||||
- BUGFIX: Fix btdigg search engine. (BTDigg research team)
|
||||
- BUGFIX: Save statistics every 15min and only if there was new traffic. Fixes #1288 and partially #1272. (sledgehammer999)
|
||||
- BUGFIX: Fix share ratio text in the 'general' tab. (sledgehammer999)
|
||||
- BUGFIX: Output a more generic message when blocking IPs and don't use italics in the log. (sledgehammer999)
|
||||
- BUGFIX: Allow 2 decimals when setting the share ratio. Closes #1303. (sledgehammer999)
|
||||
- BUGFIX: Fix extratorrents search plugin. (sledgehammer999)
|
||||
- BUGFIX: Use shorter names for amount columns in main UI (Gelmir)
|
||||
- BUGFIX: Fix overstretched options dialog. Closes #1293. (sledgehammer999)
|
||||
- BUGFIX: Don't show a popup menu when no torrent is selected. (sledgehammer999)
|
||||
- BUGFIX: Launch external programs async and don't block. Closes #1252. (sledgehammer999)
|
||||
- BUGFIX: Don't re-announce to trackers when torrent is paused. Closes #1310. (sledgehammer999)
|
||||
- BUGFIX: Bring dialog boxes in the front when qbt doesn't have focus. (sledgehammer999)
|
||||
- BUGFIX: Correctly resize 'name' column of the content tab. Closes #1360. (sledgehammer999)
|
||||
- BUGFIX: Correctly restore 'name' column width when loading magnet links in the 'Add new torrent dialog'. Closes #1334. (sledgehammer999)
|
||||
- WEBUI: Fix sorting by size in WebUI when non-default locale used. (Vladimir Golovnev)
|
||||
- UI: Reposition statistics menu item. (sledgehammer999)
|
||||
- UI: Convert more accurately decimal numbers to text. (sledgehammer999)
|
||||
- WINDOWS/OSX: Improvements on the behavior of the program updater(closes #1282) (sledgehammer999)
|
||||
- LINUX: Explicitle tell that we don't support freedesktop's startup notify standard. Fixes GNOME issues. Closes #1217. (sledgehammer999)
|
||||
- LINUX: Add our WM_CLASS in the .desktop file so window managers know how to group our windows. (sledgehammer999)
|
||||
- OTHER: Sync translations from Transifex.
|
||||
* Sat Jan 15 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.3
|
||||
- BUGFIX: Fix possible crashes in full allocation mode
|
||||
- BUGFIX: Fix icon size issues (Linux, icon theme)
|
||||
- BUGFIX: Fixed file priority context menu
|
||||
- BUGFIX: Remove dbus dependency in nox mode
|
||||
- BUGFIX: Fix compilation on FreeBSD
|
||||
- I18N: Improve Web UI translation
|
||||
- I18N: Updated Polish translation
|
||||
|
||||
* Thu 16 Jan 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.5
|
||||
- BUGFIX: Fix compilation with Qt 4.7. Closes #1215. (sledgehammer999)
|
||||
- BUGFIX: Third attempt at fixing saving settings on OS shutdown. (sledgehammer999)
|
||||
- BUGFIX: Preview now correctly uses the selected file. Closes #1222 #1182. (sledgehammer999)
|
||||
- BUGFIX: Allow to resize the columns in Add New Torrent dialog. Closes #1207 #676 (sledgehammer999)
|
||||
- BUGFIX: Ensure that at least one column in the tranferlist is always visible. Closes #1165. (sledgehammer999)
|
||||
- BUGFIX: Ensure that the options window will always be placed onscreen. Closes #1226. (sledgehammer999)
|
||||
- BUGFIX: Delete temporary files after they aren't needed. Closes #1188. (sledgehammer999)
|
||||
- BUGFIX: Correctly detect libtorrent version. (sledgehammer999)
|
||||
- BUGFIX: Various code cppcheck fixes (Konstantin Goncharik)
|
||||
- BUGFIX: Remove isohunt search engine and update thepiratebay url (sledgehammer999)
|
||||
- BUGFIX: Fix rss settings corruption when checking regexp and going to other rule. (Gelmir)
|
||||
- BUGFIX: Don't count paused torrents for the autoshutdown. Closes #1280. (sledgehammer999)
|
||||
- LINUX: Fix notifications with xfce4-notifyd.
|
||||
- OSX: Added basic retina support. Closes #1251. (Sébastien Lavoie)
|
||||
- OTHER: Sync translations from Transifex.
|
||||
* Wed Jan 12 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.2
|
||||
- BUGFIX: Do not report PeX as being disabled when DHT is
|
||||
- BUGFIX: Fix possible crash on adding magnet links
|
||||
- BUGFIX: Fix torrent import (was not working)
|
||||
- I18N: Updated Greek, Croatian, Russian, Unkrainian and Bulgarian translations
|
||||
- I18N: Added Armenian translation (New)
|
||||
- I18N: Remove country flags from program preferences (language selection)
|
||||
- I18N: Translate locale names (language selection)
|
||||
|
||||
* Sun 29 Dec 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.4
|
||||
- FEATURE: Statistics dialog (Gelmir)
|
||||
- FEATURE: Tooltips explaining each peer's connection flags (sledgehammer999)
|
||||
- FEATURE: Win/Mac Check for program updates every 15min and allow the user to manually check for updates through the help menu. (sledgehammer999)
|
||||
- BUGFIX: Better dialog message for torrent delete confirmation (sledgehammer999)
|
||||
- BUGFIX: Fix resizing grip location. Closes #1146. (sledgehammer999)
|
||||
- BUGFIX: Lock toolbar in place. Closes #1144. (sledgehammer999)
|
||||
- BUGFIX: Second attempt at fixing saving settings on shutdown. (sledgehammer999)
|
||||
- BUGFIX: Sort labels in 'Add new torrent' dialog. Closes #1150 #411. (sledgehammer999)
|
||||
- LINUX: Fix build under Ubuntu 13.10 (sledgehammer999)
|
||||
- LINUX: Make sleep and shutdown functions work on systemd's logind (Faheem Pervez)
|
||||
|
||||
* Mon Nov 20 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.3
|
||||
- FEATURE: Add a key shortcut to "Add link to torrent..." (Angel Alonso)
|
||||
- BUGFIX: Make all columns and headers use the same text alignment in the transferlist. (sledgehammer999)
|
||||
- BUGFIX: Fix build system for Unix/Linux. (sledgehammer999)
|
||||
- BUGFIX: Case insensitive sort in Peers list. Closes #1066. (sledgehammer999)
|
||||
- BUGFIX: Small optimization of WebUI responses when there isn't a data payload. (sledgehammer999)
|
||||
- BUGFIX: Hide empty folders after filtering. Closes #74. (sledgehammer999)
|
||||
- BUGFIX: Expand folders when filtering files. Closes #1076. (sledgehammer999)
|
||||
- BUGFIX: Updated search plugin's URL (Zach Thibeau)
|
||||
- BUGFIX: Strip some png to fix incorrect sRGB profiles. (Angel Alonso)
|
||||
- BUGFIX: Fixed font issues on OSX Mavericks (Zach Thibeau)
|
||||
- BUGFIX: Improve text in the About dialog (Artem S. Tashkinov)
|
||||
- BUGFIX: Always show a peer IP address as a tool tip (Artem S. Tashkinov)
|
||||
- BUGFIX: Fix inhibit system functionality. Closes #766. (sledgehammer999)
|
||||
- BUGFIX: WebUI: Don't gzip too small payloads. (sledgehammer999)
|
||||
- BUGFIX: Correctly detect if the browser supports gzip compression. (sledgehammer999)
|
||||
- BUGFIX: Fix WebUI link to 'Anonymous mode' explanation. Closes #1093. (sledgehammer999)
|
||||
- BUGFIX: Correctly update tracker tier number in the trackers tab. Closes #1075. (sledgehammer999)
|
||||
- BUGFIX: Speed improvements.(sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
|
||||
* Tue Nov 05 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.2
|
||||
- BUGFIX: Fix WebUI gzip compression. Closes #1037. (sledgehammer999)
|
||||
- BUGFIX: Fix compilation with qt < 4.8.0. Closes #1043. (sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
|
||||
* Mon Oct 28 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.1
|
||||
- FEATURE: Show external IP in the log. Closes #968. (sledgehammer999)
|
||||
- FEATURE: Enable gzip compression in the webui. It should be faster now. (sledgehammer999)
|
||||
- FEATURE: Torrents show more states(queued for checking, downloading metadata, allocating, checking resume). (sledgehammer999)
|
||||
- FEATURE: Reenable "force reannounce" to all trackers. (sledgehammer999)
|
||||
- FEATURE: Allow to clear the UI lock password. Closes #973. (sledgehammer999)
|
||||
- FEATURE: New translations: English(Australia) and English(United Kingdom)
|
||||
- BUGFIX: Expose all available translation in the WebUI. Closes #976. (sledgehammer999)
|
||||
- BUGFIX: Copy IP copied wrong data. Closes #970 (sledgehammer999)
|
||||
- BUGFIX: "Preview file..." didn't work on single file torrents. (sledgehammer999)
|
||||
- BUGFIX: Fix and improve the scheduler (Gelmir and sledgehammer999)
|
||||
- BUGFIX: RSS fixes. Closes #960, #998 (Gelmir)
|
||||
- BUGFIX: Fix 'append label to save path' with magnet links. (sledgehammer999)
|
||||
- BUGFIX: Can download up to 10MB .torrent file when a link is provided. Closes #879 (sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
- LINUX: Fix missing conf.pri error (leigh123linux)
|
||||
- WINDOWS: Don't remove file associations if they aren't our own. (sledgehammer999)
|
||||
|
||||
* Sat Oct 12 2013 - Christophe Dumez <chris@qbittorrent.org> and sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.0
|
||||
- FEATURE: Add command line option to daemonize qbittorrent-nox (ngaro)
|
||||
- FEATURE: Add "Shutdown qBittorrent" button to Web UI (ngaro)
|
||||
- FEATURE: Add setting to copy .torrent files for finished downloads (Driim)
|
||||
- FEATURE: Add option to start qBittorrent on Windows startup (sledgehammer999)
|
||||
- FEATURE: Add context menu to Web seed list (Gelmir)
|
||||
- FEATURE: Add support for tracker tiers / groups to creator (Gelmir)
|
||||
- FEATURE: Allow clearing execution and ban logs (Gelmir)
|
||||
- FEATURE: Add option to use random port on each startup (ireallylikeher)
|
||||
- FEATURE: Expose the cache expiry to the user (Gelmir)
|
||||
- FEATURE: Support Atom feeds (Gelmir)
|
||||
- FEATURE: Add "save path" column (John Peterson)
|
||||
- FEATURE: Add μTorrent-compatible "Flags" column in the peer tab(sledgehammer999)
|
||||
- FEATURE: Load magnet metadata in the background while the "Add New Torrent" Dialog is showing (Gelmir)
|
||||
- FEATURE: Allow to enter only an info-hash for download(sledgehammer999)
|
||||
- FEATURE: Bring the "Add New Torrent" Dialog to the front(glassez)
|
||||
- BUGFIX: Add confirmation dialog for "Force recheck" action (closes #131)
|
||||
- BUGFIX: Greatly improve RSS manager performance (closes #34)
|
||||
- BUGFIX: Ensure that all columns in the tranferlist have a size > 0.
|
||||
- BUGFIX: Don't mark RSS item as read when it failed to download (Gelmir)
|
||||
- BUGFIX: Fix ETA calculation when some files are downloaded and marked afterwards as 'do not download'(sledgehammer999)
|
||||
- BUGFIX: Make the UI show that PEX/DHT/LSD are actually disabled on private torrents(sledgehammer999)
|
||||
- BUGFIX: Scheduler should be much more robust and correct now(sledgehammer999)
|
||||
- BUGFIX: Now qBt won't forget torrent settings after an unclean shutdown(sledgehammer999)
|
||||
- BUGFIX: Text boxes in edit dialogs will fit to text width(Gelmir)
|
||||
- BUGFIX: Enable edit/rename via F2 or double click in various places(Gelmir)
|
||||
- BUGFIX: Allow to edit trackers and copy their urls(Gelmir and Driim)
|
||||
- BUGFIX: Add Uploaded column to main view(Gelmir)
|
||||
- BUGFIX: Calculate ETA for seeding torrents(Gelmir)
|
||||
- BUGFIX: Add option to ignore global share ratio limits for created torrents(Gelmir)
|
||||
- OTHER: Many RSS bugfixes and improvements all over the place(Gelmir)
|
||||
- OTHER: Generate translations at configure time to reduce tarball size
|
||||
- OTHER: Make peer tab sortable by ip too (Gelmir)
|
||||
- OTHER: Translations moved to Transifex(https://www.transifex.com/projects/p/qbittorrent/)
|
||||
- OTHER: New Translation - Vietnamese (Anh Phan)
|
||||
- PERFORMANCE: Impove drawing speed of tranferlist when there are many torrents(>100)
|
||||
- PERFORMANCE: Impove drawing speed of peers list when there are many peers
|
||||
|
||||
* Thu Aug 09 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.0
|
||||
- FEATURE: Brand new torrent addition dialog
|
||||
- FEATURE: Add the ability to choose the save path when using magnet links (mutoso)
|
||||
- FEATURE: Add support for adding multiple local torrents at once (Web UI)
|
||||
- COSMETIC: Improve style of left panel
|
||||
- BUGFIX: Lower panels no longer gets disabled
|
||||
- BUGFIX: Major code refactoring and various optimizations.
|
||||
- BUGFIX: No longer strip root folder from torrent files
|
||||
- OTHER: Drop support for libtorrent v0.14.x
|
||||
- OTHER: Drop support for Qt 4.5
|
||||
|
||||
* Sat Oct 08 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.0
|
||||
- FEATURE: Add file association settings to program preferences (Windows)
|
||||
- FEATURE: Add setting to ignore slow torrents in queueing system
|
||||
- FEATURE: Add advanced setting to announce to all trackers
|
||||
- FEATURE: Add support for anonymous mode (libtorrent >= v0.16)
|
||||
- FEATURE: Add quick "set as default save path" checkbox to torrent addition dialog (sledgehammer999)
|
||||
- BUGFIX: Add tray menu entry for toggling window visibility
|
||||
- BUGFIX: Fix execution log lines selection and copying
|
||||
- BUGFIX: Reduce CPU usage when running Web UI
|
||||
- BUGFIX: Save RSS items to disk regularly for safety
|
||||
- BUGFIX: Fix ratio calculation (use all_time_download)
|
||||
- BUGFIX: Fix torrent upload issues (Web UI)
|
||||
- BUGFIX: Fix some IE incompatibilities (Web UI)
|
||||
- COSMETIC: Display speed at the beginning of the Window title
|
||||
- COSMETIC: Several cosmetic fixes to the Web UI
|
||||
- COSMETIC: Make top toolbar follow system style
|
||||
- OTHER: Display libraries versions in about dialog (sledgehammer999)
|
||||
- OTHER: Display qBittorrent version in Web UI about dialog
|
||||
|
||||
* Thu Jun 02 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.8.0
|
||||
- FEATURE: Added full libtorrent v0.16 support (uTP, ...)
|
||||
- FEATURE: Proxy can be disabled for peer connections
|
||||
- FEATURE: Added support for secure SMTP connection (SSL)
|
||||
- FEATURE: Added support for SMTP authentication
|
||||
- FEATURE: Added UPnP/NAT-PMP port forward for the Web UI port
|
||||
- FEATURE: qBittorrent can update dynamic DNS services (DynDNS, no-ip)
|
||||
- FEATURE: Display peer connection type in peer list (BT, uTP, Web)
|
||||
- FEATURE: Added full regex support to RSS downloader
|
||||
- FEATURE: Added regex help and validation in RSS downloader
|
||||
- FEATURE: Added HTTPS support to Web UI (Ishan Arora)
|
||||
- BUGFIX: Change systray icon on the fly (no restart needed)
|
||||
- BUGFIX: Remember peer-level rate limits (requires libtorrent v0.16)
|
||||
- BUGFIX: Stop annoncing to trackers an all tiers (more respectful)
|
||||
- BUGFIX: Stop sharing private trackers with other peers
|
||||
- BUGFIX: Tracker exchange extension can be disabled
|
||||
- BUGFIX: Cleaner program exit on system log out
|
||||
- BUGFIX: Fix possible magnet link parsing problems
|
||||
- BUGFIX: Fix possible RSS URL parsing problems
|
||||
- COSMETIC: Added monochrome icon for light themes
|
||||
|
||||
* Sun Mar 20 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.7.0
|
||||
- FEATURE: Added search field for torrent content
|
||||
- FEATURE: Added auto-shutdown confirmation dialog
|
||||
- FEATURE: Added option to skip torrent deletion confirmation (Ville Kiiskinen)
|
||||
- FEATURE: IP address reported to trackers is now customizable
|
||||
- FEATURE: Inhibit system sleep when torrents are active (Vladimir Golovnev)
|
||||
- FEATURE: Added option to bypass Web UI authentication for localhost
|
||||
- FEATURE: Added option to disable program exit confirmation
|
||||
- FEATURE: Added per-torrent ratio limiting (Christian Kandeler)
|
||||
- FEATURE: Torrent content list is now sortable
|
||||
- BUGFIX: Fix compilation with namespaced Qt (Christian Kandeler)
|
||||
- BUGFIX: Added length restriction on UI lock password
|
||||
- COSMETIC: Added monochrome tray icon
|
||||
- COSMETIC: Improved status bar's style
|
||||
- OTHER: Make QtDBus dependency optional (X11)
|
||||
* Mon Jan 10 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.1
|
||||
- BUGFIX: Really disable torrent addition dialog by default
|
||||
- BUGFIX: Fix some missing icons in the Web UI
|
||||
- BUGFIX: Fix magnet torrent name update problem
|
||||
- COSMETIC: Use 24px size for toolbar icons and reduce spacing
|
||||
- COSMETIC: Move transfer list filter on the right side of the toolbar
|
||||
|
||||
* Sun Jan 9 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.0
|
||||
- FEATURE: Use system icons (Linux, Qt >= 4.6)
|
||||
|
||||
16
INSTALL
@@ -10,23 +10,25 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
|
||||
Dependencies:
|
||||
- Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
||||
- Qt >= 4.5.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
|
||||
|
||||
- pkg-config executable
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.15.0)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, compatible with v0.15.x)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
- libboost 1.34.x (libboost-filesystem°) + libasio
|
||||
- libboost 1.34.x (libboost-filesystem, libboost-date-time) + libasio
|
||||
or
|
||||
- libboost >= 1.35.x (libboost-system, libboost-filesystem°)
|
||||
|
||||
°libboost-filesystem is not needed if libtorrent-rasterbar >= v0.16.x is used
|
||||
- libboost >= 1.35.x (libboost-system, libboost-filesystem, libboost-date-time)
|
||||
|
||||
- python >= 2.3 (needed by search engine)
|
||||
* Run time only dependency
|
||||
|
||||
- libnotify >= 0.4.2, glib-2.0 (optional)
|
||||
* Can be used for system notifications to replace standard Qt notifications
|
||||
so that it integrates better into the Desktop
|
||||
|
||||
- geoip-database (optional)
|
||||
* If qBittorrent cannot find this database, it will try to resolve countries using the Internet but it will be a lot slower.
|
||||
* Run time only dependency
|
||||
@@ -44,7 +46,7 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
|
||||
- pkg-config executable
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= v0.15.0)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, >= v0.15.0 ADVISED)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
qBittorrent - A BitTorrent client in Qt
|
||||
qBittorrent - A BitTorrent client in Qt4
|
||||
------------------------------------------
|
||||
|
||||
[](https://travis-ci.org/qbittorrent/qBittorrent)
|
||||
Description:
|
||||
********************************
|
||||
###Description:
|
||||
qBittorrent is a bittorrent client programmed in C++ / Qt that uses
|
||||
libtorrent (sometimes called libtorrent-rasterbar) by Arvid Norberg.
|
||||
qBittorrent is a bittorrent client programmed in C++ / Qt4 that uses
|
||||
libtorrent (sometimes called rblibtorrent) by Arvid Norberg.
|
||||
|
||||
It aims to be a good alternative to all other bittorrent clients
|
||||
out there. qBittorrent is fast, stable and provides unicode
|
||||
@@ -14,14 +13,13 @@ support as well as many features.
|
||||
This product includes GeoLite data created by MaxMind, available from
|
||||
http://maxmind.com/
|
||||
|
||||
### Installation:
|
||||
Installation:
|
||||
********************************
|
||||
For installation, follow the instructions from INSTALL file, but simple:
|
||||
|
||||
```
|
||||
./configure
|
||||
make && make install
|
||||
qbittorrent
|
||||
```
|
||||
|
||||
will install and execute qBittorrent hopefully without any problem.
|
||||
|
||||
@@ -34,9 +32,9 @@ http://wiki.qbittorrent.org
|
||||
Please report any bug (or feature request) to:
|
||||
http://bugs.qbittorrent.org
|
||||
|
||||
You can also meet me (sledgehammer_999) on IRC:
|
||||
`#qbittorrent on irc.freenode.net`
|
||||
You can also meet me (chris-qBT) on IRC:
|
||||
#qbittorrent on irc.freenode.net
|
||||
|
||||
------------------------------------------
|
||||
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||
Christophe Dumez <chris@qbittorrent.org>
|
||||
|
||||
16
README.os2
@@ -27,6 +27,7 @@ First you need to create the conf.pri file in the same dir as this readme.os2 is
|
||||
the conf.pri file has the following content:
|
||||
|
||||
##### conf.pri content beginn #####
|
||||
PREFIX = .
|
||||
BINDIR = ./bin
|
||||
INCDIR = ./include
|
||||
LIBDIR = ./lib
|
||||
@@ -42,10 +43,7 @@ LIBS += -Lx:/trees/libtorrent/trunk/src/.libs \
|
||||
|
||||
Of course all the above path references have to be adjusted to your build env.
|
||||
|
||||
Now you can either do a normal build or a shadow build. A shadow build has the
|
||||
advantage that no created files are in the same dir as the sources are.
|
||||
|
||||
For a normal build do the following:
|
||||
It should now be easy to build qBittorrent:
|
||||
|
||||
Simply type:
|
||||
$ qmake
|
||||
@@ -53,16 +51,6 @@ $ qmake
|
||||
Followed by:
|
||||
$ make
|
||||
|
||||
For a shadow build do the following:
|
||||
given your sources are in x:\trees\qbittorrent\trunk create a
|
||||
x:\trees\qbittorrent\build directory
|
||||
|
||||
Now switch to the created directory and type:
|
||||
$ qmake ..\trunk
|
||||
|
||||
Followed by:
|
||||
$ make
|
||||
|
||||
If all works fine you should get a working qbittorrent executable.
|
||||
|
||||
If you have any question regarding the eCS (OS/2) port of qBittorrent you can meet me (_diver) on IRC:
|
||||
|
||||
253
configure
vendored
@@ -22,11 +22,11 @@ Dependency options:
|
||||
--disable-gui Disable qBittorrent
|
||||
Graphical user interface for
|
||||
headless running
|
||||
--disable-qt-dbus Disable use of qt-dbus
|
||||
--with-libboost-inc=[path] Path to libboost include
|
||||
files
|
||||
--with-libboost-lib=[path] Path to libboost library
|
||||
files
|
||||
--disable-libnotify Disable use of libnotify
|
||||
--disable-geoip-database Disable use of geoip-database
|
||||
--with-geoip-database-embedded Geoip Database will be
|
||||
embedded in qBittorrent
|
||||
@@ -162,11 +162,6 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-qt-dbus)
|
||||
QC_DISABLE_qt_dbus="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libboost-inc=*)
|
||||
QC_WITH_LIBBOOST_INC=$optarg
|
||||
shift
|
||||
@@ -177,6 +172,11 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-libnotify)
|
||||
QC_DISABLE_libnotify="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-geoip-database)
|
||||
QC_DISABLE_geoip_database="Y"
|
||||
shift
|
||||
@@ -215,9 +215,9 @@ echo DATADIR=$DATADIR
|
||||
echo EX_QTDIR=$EX_QTDIR
|
||||
echo QC_ENABLE_DEBUG=$QC_ENABLE_DEBUG
|
||||
echo QC_DISABLE_GUI=$QC_DISABLE_GUI
|
||||
echo QC_DISABLE_qt_dbus=$QC_DISABLE_qt_dbus
|
||||
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
||||
echo QC_WITH_LIBBOOST_LIB=$QC_WITH_LIBBOOST_LIB
|
||||
echo QC_DISABLE_libnotify=$QC_DISABLE_libnotify
|
||||
echo QC_DISABLE_geoip_database=$QC_DISABLE_geoip_database
|
||||
echo QC_WITH_GEOIP_DATABASE_EMBEDDED=$QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
echo QC_WITH_QTSINGLEAPPLICATION=$QC_WITH_QTSINGLEAPPLICATION
|
||||
@@ -325,7 +325,7 @@ cat >$1/modules.cpp <<EOT
|
||||
#line 1 "qt4.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.6
|
||||
name: Qt >= 4.5
|
||||
arg: enable-debug, Enable debug mode
|
||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||
-----END QCMOD-----
|
||||
@@ -334,8 +334,8 @@ class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.6"; }
|
||||
QString shortname() const { return "Qt 4.6"; }
|
||||
QString name() const { return "Qt >= 4.5"; }
|
||||
QString shortname() const { return "Qt 4.5"; }
|
||||
bool exec()
|
||||
{
|
||||
// NOX mode
|
||||
@@ -344,11 +344,7 @@ public:
|
||||
}
|
||||
// Debug mode
|
||||
if(!conf->getenv("QC_ENABLE_DEBUG").isEmpty()) {
|
||||
conf->addExtra("CONFIG -= release");
|
||||
conf->addExtra("CONFIG += debug");
|
||||
} else {
|
||||
conf->addExtra("CONFIG -= debug");
|
||||
conf->addExtra("CONFIG += release");
|
||||
}
|
||||
#ifdef Q_OS_FREEBSD
|
||||
conf->addLib("-lexecinfo");
|
||||
@@ -356,39 +352,7 @@ public:
|
||||
#else
|
||||
conf->addExtra("MANPREFIX = \$\$PREFIX/share");
|
||||
#endif
|
||||
return(QT_VERSION >= 0x040600);
|
||||
}
|
||||
};
|
||||
#line 1 "qt-dbus.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-dbus
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_dbus : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_dbus(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtDBus >= 4.5"; }
|
||||
QString shortname() const { return "qt-dbus"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtDBus", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += dbus");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return(QT_VERSION >= 0x040500);
|
||||
}
|
||||
};
|
||||
#line 1 "pkg-config.qcm"
|
||||
@@ -419,17 +383,20 @@ class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.15.0"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.4"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.15.0";
|
||||
QString req_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -442,15 +409,12 @@ arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
@@ -474,62 +438,141 @@ public:
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
bool exec(){
|
||||
QStringList sl;
|
||||
QString s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if (!s.isEmpty())
|
||||
sl << s;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach (s, sl) {
|
||||
if (conf->checkHeader(s, "boost/format.hpp")
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
&& conf->checkHeader(s, "boost/filesystem/path.hpp")
|
||||
#endif
|
||||
) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
conf->addIncludePath(s);
|
||||
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "boost/format.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "boost/format.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
required_libs << "filesystem" ;
|
||||
#endif
|
||||
//required_libs << "thread";
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" ;
|
||||
}
|
||||
QStringList libDirs;
|
||||
if (!s.isEmpty())
|
||||
libDirs << s;
|
||||
libDirs << "/usr/lib/" << "/usr/lib/i386-linux-gnu/" << "/usr/lib64/" << "/usr/lib/x86_64-linux-gnu/" << "/usr/local/lib/" << "/usr/lib/local/i386-linux-gnu/" << "/usr/local/lib64/" << "/usr/local/lib/x86_64-linux-gnu/";
|
||||
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
foreach(const QString& lib, required_libs) {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "libnotify.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libnotify
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libnotify : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libnotify(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libnotify >= 0.4.2 (optional)"; }
|
||||
QString shortname() const { return "libnotify"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_libnotify").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_libnotify").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
QStringList incs;
|
||||
QString req_ver = "0.4.2";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("libnotify", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += libnotify");
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
QStringList incs2;
|
||||
QString req_ver2 = "2.0";
|
||||
QString version2, libs2, other2;
|
||||
if(conf->findPkgConfig("glib-2.0", mode, req_ver2, &version2, &incs2, &libs2, &other2)) {
|
||||
for(int n = 0; n < incs2.count(); ++n)
|
||||
conf->addIncludePath(incs2[n]);
|
||||
if(!libs2.isEmpty())
|
||||
conf->addLib(libs2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
QStringList incs3;
|
||||
QString req_ver3 = "2.0";
|
||||
QString version3, libs3, other3;
|
||||
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
|
||||
for(int n = 0; n < incs3.count(); ++n)
|
||||
conf->addIncludePath(incs3[n]);
|
||||
if(!libs3.isEmpty())
|
||||
conf->addLib(libs3);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "geoip-database.qcm"
|
||||
/*
|
||||
@@ -602,9 +645,6 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_qt4(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_qt_dbus(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_pkg_config(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
@@ -614,6 +654,9 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_libboost(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_libnotify(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_geoip_database(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
@@ -1567,9 +1610,9 @@ export DATADIR
|
||||
export EX_QTDIR
|
||||
export QC_ENABLE_DEBUG
|
||||
export QC_DISABLE_GUI
|
||||
export QC_DISABLE_qt_dbus
|
||||
export QC_WITH_LIBBOOST_INC
|
||||
export QC_WITH_LIBBOOST_LIB
|
||||
export QC_DISABLE_libnotify
|
||||
export QC_DISABLE_geoip_database
|
||||
export QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
export QC_WITH_QTSINGLEAPPLICATION
|
||||
|
||||
@@ -8,7 +8,7 @@ qBittorrent\-nox \- a command line Bittorrent client written in C++ / Qt4
|
||||
|
||||
.SH "SYNOPSIS"
|
||||
|
||||
\fBqbittorrent\-nox\fR [\-\-d|\-\-daemon] [\-\-webui-port=x] [TORRENT_FILE | URL]...
|
||||
\fBqbittorrent\-nox\fR [\-\-webui-port=x] [TORRENT_FILE | URL]...
|
||||
|
||||
\fBqbittorrent\-nox\fR \-\-help
|
||||
|
||||
|
||||
131
install.os2
@@ -11,7 +11,7 @@ QBittorrent installation
|
||||
|
||||
3. INSTALLATION
|
||||
|
||||
4. BUGREPORTS
|
||||
4. CONTACT
|
||||
|
||||
5. CREDITS
|
||||
|
||||
@@ -29,70 +29,17 @@ Welcome to QBittorrent port for OS/2 and eComStation.
|
||||
2. REQUIREMENTS
|
||||
===============
|
||||
|
||||
The following requirements can be installed either by rpm or by zip files.
|
||||
* klibc 0.6.3 or later
|
||||
|
||||
RPM Installation:
|
||||
ftp://ftp.netlabs.org/pub/gcc/libc-0_6_3-csd3.wpi
|
||||
|
||||
klibc
|
||||
-----
|
||||
* openssl 1.0
|
||||
|
||||
ftp://ftp.netlabs.org/pub/unixos2/ssl10.zip
|
||||
|
||||
1. yum install libc
|
||||
* Qt4 dll
|
||||
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. yum install openssl
|
||||
|
||||
pthread
|
||||
-------
|
||||
|
||||
1. yum install pthread
|
||||
|
||||
GCC4Core
|
||||
--------
|
||||
|
||||
1. yum install libgcc
|
||||
2. yum install gcc-stack-protector
|
||||
3. yum install gcc-stdc++-shared-library
|
||||
4. yum install gcc-supc++-shared-library
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. yum install libqt4
|
||||
|
||||
|
||||
ZIP Installation:
|
||||
|
||||
klibc
|
||||
-----
|
||||
|
||||
1. Download klibc 0.6.5 or better (see http://svn.netlabs.org/libc for more information)
|
||||
2. Install the files to your libpath eg x:\ecs\dll
|
||||
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. Download the zip file from http://rpm.netlabs.org/release/00/zip
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
pthread
|
||||
-------
|
||||
|
||||
1. Download pthread 2012-03-13 or better from http://rpm.netlabs.org/release/00/zip
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
GCC4Core
|
||||
--------
|
||||
|
||||
1. Download GCC4Core 1.2.1 or better from http://ftp.netlabs.org/pub/gcc
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. Download Qt4 4.7.3 or better (see http://svn.netlabs.org/qt4 for more information)
|
||||
2. Install the files according to the readme
|
||||
see http://svn.netlabs.org/qt4 for more information whats needed and where to get the latest
|
||||
|
||||
|
||||
3. INSTALLATION
|
||||
@@ -100,6 +47,30 @@ Qt4 dll
|
||||
|
||||
To install QBittorrent, do the following:
|
||||
|
||||
klibc
|
||||
-----
|
||||
|
||||
1. Download klibc 0.6.3 csd3 or later.
|
||||
2. Install the package by double-clicking on the WPI file.
|
||||
|
||||
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. Download the zip file
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. Download the package
|
||||
2. Install the package by double-clicking on the wpi file.
|
||||
|
||||
|
||||
|
||||
QBittorrent
|
||||
-----------
|
||||
|
||||
1. Create a directory for QBittorrent.
|
||||
2. Extract the QBittorrent package to the new directory.
|
||||
3. Create a WPS object for QBittorrent.exe.
|
||||
@@ -107,13 +78,18 @@ To install QBittorrent, do the following:
|
||||
5. Happy torrenting
|
||||
|
||||
|
||||
4. BUGREPORTS
|
||||
=============
|
||||
|
||||
Please create bugreports at http://svn.netlabs.org/qtapps
|
||||
4. CONTACT
|
||||
==========
|
||||
|
||||
Please send bugreports to:
|
||||
|
||||
ecs@aroa.ch
|
||||
|
||||
Only bug reports with a reproducable bug are accepted. :-)
|
||||
|
||||
|
||||
|
||||
5. CREDITS
|
||||
==========
|
||||
|
||||
@@ -146,33 +122,6 @@ development, you can do so in one of the following ways:
|
||||
7. HISTORY
|
||||
==========
|
||||
|
||||
2012-09-19
|
||||
|
||||
* updated to 3.0.4 code level of QBittorrent
|
||||
* updated libtorrent to 0.16.3 level
|
||||
|
||||
2012-09-06
|
||||
|
||||
* updated to 3.0.2 code level of QBittorrent
|
||||
|
||||
2012-05-14
|
||||
|
||||
* updated to 2.9.8 code level of QBittorrent
|
||||
|
||||
2012-03-15
|
||||
|
||||
* updated to 2.9.5 code level of QBittorrent
|
||||
|
||||
2011-09-26
|
||||
|
||||
* updated to 2.8.5 code level of QBittorrent
|
||||
* updated to Qt 4.7.3
|
||||
|
||||
2011-06-20
|
||||
|
||||
* updated to 2.7.3 code level of QBittorrent
|
||||
* updated libtorrent to 0.15.6 level
|
||||
|
||||
2010-12-23
|
||||
|
||||
* updated to 2.5.2 code level of QBittorrent
|
||||
|
||||
63
macxconf.pri
@@ -2,66 +2,15 @@ PREFIX = /usr/local
|
||||
BINDIR = /usr/local/bin
|
||||
DATADIR = /usr/local/share
|
||||
|
||||
# Use pkg-config to get all necessary libtorrent DEFINES
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libtorrent-rasterbar
|
||||
DEFINES += BOOST_ASIO_DYN_LINK
|
||||
|
||||
# Special include/libs paths (macports)
|
||||
INCLUDEPATH += /usr/include/openssl /usr/include /opt/local/include/boost /opt/local/include
|
||||
LIBS += -L/opt/local/lib
|
||||
|
||||
# OpenSSL lib
|
||||
LIBS += -lssl -lcrypto
|
||||
# Boost system lib
|
||||
LIBS += -lboost_system-mt
|
||||
# Boost filesystem lib (Not needed for libtorrent >= 0.16.0)
|
||||
#LIBS += -lboost_filesystem-mt
|
||||
# Carbon
|
||||
LIBS += -framework Carbon -framework IOKit
|
||||
# Zlib
|
||||
LIBS += -lz
|
||||
INCLUDEPATH += /usr/local/include/libtorrent /usr/include/openssl /usr/include /opt/local/include/boost /opt/local/include
|
||||
LIBS += -ltorrent-rasterbar -lcrypto -L/opt/local/lib -lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt -framework Cocoa -framework Carbon
|
||||
|
||||
document_icon.path = Contents/Resources
|
||||
document_icon.files = mac/qBitTorrentDocument.icns
|
||||
document_icon.files = Icons/qBitTorrentDocument.icns
|
||||
|
||||
QMAKE_BUNDLE_DATA += document_icon
|
||||
|
||||
qt_conf.path = Contents/Resources
|
||||
qt_conf.files = mac/qt.conf
|
||||
QMAKE_BUNDLE_DATA += qt_conf
|
||||
|
||||
qt_translations.path = Contents/MacOS/translations
|
||||
qt_translations.files = qt-translations/qt_ar.qm \
|
||||
qt-translations/qt_bg.qm \
|
||||
qt-translations/qt_ca.qm \
|
||||
qt-translations/qt_cs.qm \
|
||||
qt-translations/qt_da.qm \
|
||||
qt-translations/qt_de.qm \
|
||||
qt-translations/qt_es.qm \
|
||||
qt-translations/qt_fi.qm \
|
||||
qt-translations/qt_fr.qm \
|
||||
qt-translations/qt_gl.qm \
|
||||
qt-translations/qt_he.qm \
|
||||
qt-translations/qt_hu.qm \
|
||||
qt-translations/qt_it.qm \
|
||||
qt-translations/qt_ja.qm \
|
||||
qt-translations/qt_ko.qm \
|
||||
qt-translations/qt_lt.qm \
|
||||
qt-translations/qt_nl.qm \
|
||||
qt-translations/qt_pl.qm \
|
||||
qt-translations/qt_pt.qm \
|
||||
qt-translations/qt_pt_BR.qm \
|
||||
qt-translations/qt_ru.qm \
|
||||
qt-translations/qt_sk.qm \
|
||||
qt-translations/qt_sv.qm \
|
||||
qt-translations/qt_tr.qm \
|
||||
qt-translations/qt_uk.qm \
|
||||
qt-translations/qt_zh_CN.qm \
|
||||
qt-translations/qt_zh_TW.qm
|
||||
QMAKE_BUNDLE_DATA += qt_translations
|
||||
|
||||
ICON = mac/qbittorrent_mac.icns
|
||||
QMAKE_INFO_PLIST = mac/Info.plist
|
||||
ICON = Icons/qbittorrent_mac.icns
|
||||
QMAKE_INFO_PLIST = Info.plist
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On Mac OS X, GeoIP database must be embedded.")
|
||||
|
||||
@@ -7,13 +7,9 @@ LIBS += -ltorrent-rasterbar \
|
||||
-lboost_thread \
|
||||
-lboost_system \
|
||||
-lboost_filesystem \
|
||||
-lssl -lcrypto -lidn -lpthread -lz
|
||||
-lssl -lcrypto -lidn -lpthread
|
||||
|
||||
RC_FILE = qbittorrent_os2.rc
|
||||
|
||||
# LIBTORRENT DEFINES
|
||||
DEFINES += WITH_SHIPPED_GEOIP_H
|
||||
DEFINES += BOOST_ASIO_DYN_LINK
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On eCS(OS/2), GeoIP database must be embedded.")
|
||||
|
||||
@@ -2,18 +2,3 @@ TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += src
|
||||
|
||||
include(version.pri)
|
||||
include(qm_gen.pri)
|
||||
|
||||
# Dist
|
||||
dist.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
|
||||
dist.commands += git clone . ../$${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.git &&
|
||||
dist.commands += rm -f ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.gitignore &&
|
||||
dist.commands += cd .. &&
|
||||
dist.commands += tar czf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar.gz $${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += tar cf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar $${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += xz -f $${PROJECT_NAME}-$${PROJECT_VERSION}.tar &&
|
||||
dist.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION}
|
||||
|
||||
QMAKE_EXTRA_TARGETS += dist
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
<dep type='qt4'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='qt-dbus'>
|
||||
</dep>
|
||||
<dep type='pkg-config'>
|
||||
<required/>
|
||||
</dep>
|
||||
@@ -17,6 +15,8 @@
|
||||
<dep type='libboost'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libnotify'>
|
||||
</dep>
|
||||
<dep type='geoip-database'>
|
||||
</dep>
|
||||
<dep type='qtsingleapplication'>
|
||||
|
||||
119
qcm/libboost.qcm
@@ -6,15 +6,12 @@ arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
@@ -38,60 +35,78 @@ public:
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
bool exec(){
|
||||
QStringList sl;
|
||||
QString s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if (!s.isEmpty())
|
||||
sl << s;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach (s, sl) {
|
||||
if (conf->checkHeader(s, "boost/format.hpp")
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
&& conf->checkHeader(s, "boost/filesystem/path.hpp")
|
||||
#endif
|
||||
) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
conf->addIncludePath(s);
|
||||
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "boost/format.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "boost/format.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
required_libs << "filesystem" ;
|
||||
#endif
|
||||
//required_libs << "thread";
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" ;
|
||||
}
|
||||
QStringList libDirs;
|
||||
if (!s.isEmpty())
|
||||
libDirs << s;
|
||||
libDirs << "/usr/lib/" << "/usr/lib/i386-linux-gnu/" << "/usr/lib64/" << "/usr/lib/x86_64-linux-gnu/" << "/usr/local/lib/" << "/usr/lib/local/i386-linux-gnu/" << "/usr/local/lib64/" << "/usr/local/lib/x86_64-linux-gnu/";
|
||||
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
foreach(const QString& lib, required_libs) {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,17 +8,20 @@ class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.15.0"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.4"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.15.0";
|
||||
QString req_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-dbus
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_dbus : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_dbus(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtDBus >= 4.5"; }
|
||||
QString shortname() const { return "qt-dbus"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtDBus", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += dbus");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-svg
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_svg : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_svg(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtSvg >= 4.5"; }
|
||||
QString shortname() const { return "qt-svg"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_svg").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_svg").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtSvg", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += svg");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
12
qcm/qt4.qcm
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.6
|
||||
name: Qt >= 4.5
|
||||
arg: enable-debug, Enable debug mode
|
||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||
-----END QCMOD-----
|
||||
@@ -9,8 +9,8 @@ class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.6"; }
|
||||
QString shortname() const { return "Qt 4.6"; }
|
||||
QString name() const { return "Qt >= 4.5"; }
|
||||
QString shortname() const { return "Qt 4.5"; }
|
||||
bool exec()
|
||||
{
|
||||
// NOX mode
|
||||
@@ -19,11 +19,7 @@ public:
|
||||
}
|
||||
// Debug mode
|
||||
if(!conf->getenv("QC_ENABLE_DEBUG").isEmpty()) {
|
||||
conf->addExtra("CONFIG -= release");
|
||||
conf->addExtra("CONFIG += debug");
|
||||
} else {
|
||||
conf->addExtra("CONFIG -= debug");
|
||||
conf->addExtra("CONFIG += release");
|
||||
}
|
||||
#ifdef Q_OS_FREEBSD
|
||||
conf->addLib("-lexecinfo");
|
||||
@@ -31,6 +27,6 @@ public:
|
||||
#else
|
||||
conf->addExtra("MANPREFIX = $$PREFIX/share");
|
||||
#endif
|
||||
return(QT_VERSION >= 0x040600);
|
||||
return(QT_VERSION >= 0x040500);
|
||||
}
|
||||
};
|
||||
|
||||
19
qm_gen.pri
@@ -1,19 +0,0 @@
|
||||
TS_IN = $$fromfile(src/src.pro,TRANSLATIONS)
|
||||
TS_IN_NOEXT = $$replace(TS_IN,".ts","")
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32|os2:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
unix {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt4 }
|
||||
} else {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
|
||||
}
|
||||
}
|
||||
|
||||
message("Building translations")
|
||||
for(L,TS_IN_NOEXT) {
|
||||
message("Processing $${L}")
|
||||
system("$$QMAKE_LRELEASE -silent src/$${L}.ts -qm src/$${L}.qm")
|
||||
!exists("src/$${L}.qm"):error("Building translations failed, cannot continue")
|
||||
}
|
||||
BIN
src/Icons/downarrow.png
Normal file
|
After Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 651 B |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,121 +1,39 @@
|
||||
[Desktop Entry]
|
||||
Categories=Network;FileTransfer;P2P;Qt;
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V2.6.9
|
||||
Exec=qbittorrent %U
|
||||
GenericName=BitTorrent client
|
||||
Comment=Download and share files over BitTorrent
|
||||
GenericName[ar]=العميل BitTorrent
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[cs]=BitTorrent klient
|
||||
GenericName[de]=BitTorren Client
|
||||
GenericName[el]=BitTorrent πελάτης
|
||||
GenericName[es]=Cliente BitTorrent
|
||||
GenericName[fi]=BitTorrent-ohjelma
|
||||
GenericName[fr]=Client BitTorrent
|
||||
GenericName[hr]=BitTorrent klijent
|
||||
GenericName[hu]=BitTorrent kliens
|
||||
GenericName[it]=Client BitTorrent
|
||||
GenericName[ja]=BitTorrent クライアント
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
GenericName[lt]=BitTorrent klientas
|
||||
GenericName[nl]=BitTorrent-cliënt
|
||||
GenericName[pl]=Klient BitTorrent
|
||||
GenericName[pt]=Cliente BitTorrent
|
||||
GenericName[pt_BR]=Cliente BitTorrent
|
||||
GenericName[ro]=Client BitTorrent
|
||||
GenericName[ru]=клиент BitTorrent
|
||||
GenericName[sk]=Klient siete BitTorrent
|
||||
GenericName[sr]=BitTorrent-клијент
|
||||
GenericName[sv]=BitTorrent-klient
|
||||
GenericName[tr]=BitTorrent istemcisi
|
||||
GenericName[uk]=BitTorrent-клієнт
|
||||
GenericName[zh]=BitTorrent之用户
|
||||
GenericName[zh_TW]=BitTorrent客戶端
|
||||
Icon=qbittorrent
|
||||
MimeType=application/x-bittorrent;x-scheme-handler/magnet;
|
||||
Name=qBittorrent
|
||||
Name[ko]=큐비토런트
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=false
|
||||
StartupWMClass=qbittorrent
|
||||
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
GenericName[ar]=العميل BitTorrent
|
||||
Comment[be]=Сцягванне і раздача файлаў праз пратакол BitTorrent
|
||||
GenericName[be]=BitTorrent-кліент
|
||||
Name[be]=qBittorrent
|
||||
Icon[be]=qbittorrent
|
||||
GenericName[bg]=Торент клиент
|
||||
Comment[cs]=Stahování a sdílení souborů přes síť BitTorrent
|
||||
GenericName[cs]=BitTorrent klient
|
||||
Name[cs]=qBittorrent
|
||||
Icon[cs]=qbittorrent
|
||||
GenericName[de]=BitTorren Client
|
||||
Comment[el]=Λήψη και διαμοιρασμός αρχείων μέσω BitTorrent
|
||||
GenericName[el]=BitTorrent πελάτης
|
||||
Name[el]=qBittorrent
|
||||
Icon[el]=qbittorrent
|
||||
Comment[en_GB]=Download and share files over BitTorrent
|
||||
GenericName[en_GB]=BitTorrent client
|
||||
Name[en_GB]=qBittorrent
|
||||
Icon[en_GB]=qbittorrent
|
||||
Comment[es]=Descarga y comparte archivos por BitTorrent
|
||||
GenericName[es]=Cliente BitTorrent
|
||||
Name[es]=qBittorrent
|
||||
Icon[es]=qbittorrent
|
||||
Comment[eu]=Jeitsi eta elkarbanatu agiriak BitTorrent-en
|
||||
GenericName[eu]=BitTorrent bezeroa
|
||||
Name[eu]=qBittorrent
|
||||
Icon[eu]=qbittorrent
|
||||
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
||||
GenericName[fi]=BitTorrent-ohjelma
|
||||
Name[fi]=qBittorrent
|
||||
Icon[fi]=qbittorrent
|
||||
Comment[fr]=Télécharger et partager des fichiers avec BitTorrent
|
||||
GenericName[fr]=Client BitTorrent
|
||||
Comment[gl]=Descargue e comparta ficheiros co protocolo BitTorrent
|
||||
GenericName[gl]=Cliente BitTorrent
|
||||
Name[gl]=qBittorrent
|
||||
Icon[gl]=qbittorrent
|
||||
GenericName[hr]=BitTorrent klijent
|
||||
GenericName[hu]=BitTorrent kliens
|
||||
Comment[it]=Client BitTorrent per il download di file via internet
|
||||
GenericName[it]=Client BitTorrent
|
||||
Name[it]=qBittorrent
|
||||
Icon[it]=qbittorrent
|
||||
Comment[ja]=BitTorrent でファイルをダウンロードおよび共有します
|
||||
GenericName[ja]=BitTorrent クライアント
|
||||
Name[ja]=qBittorrent
|
||||
Icon[ja]=qbittorrent
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
Name[ko]=큐비토런트
|
||||
GenericName[zh]=BitTorrent之用户
|
||||
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
||||
GenericName[lt]=BitTorrent klientas
|
||||
Name[lt]=qBittorrent
|
||||
Icon[lt]=qbittorrent
|
||||
Comment[nb]=Last ned og del filer over BitTorrent
|
||||
GenericName[nb]=BitTorrent-klient
|
||||
Name[nb]=qBittorrent
|
||||
Icon[nb]=qbittorrent
|
||||
GenericName[nl]=BitTorrent-cliënt
|
||||
Comment[pl]=Dzielenie się plikami przez BitTorrent
|
||||
GenericName[pl]=Klient BitTorrent
|
||||
Name[pl]=qBittorrent
|
||||
Icon[pl]=qbittorrent
|
||||
Comment[pt]=Transferir e partilhar ficheiros por BitTorrent
|
||||
GenericName[pt]=Aplicação BitTorrent
|
||||
Name[pt]=qBittorrent
|
||||
Icon[pt]=qbittorrent
|
||||
Comment[pt_BR]=Baixe e compartilhe arquivos através do qBittorrent
|
||||
GenericName[pt_BR]=Cliente BitTorrent
|
||||
Name[pt_BR]=qBittorrent
|
||||
Icon[pt_BR]=qbittorrent
|
||||
Comment[ro]=Descărcați și partajați fișiere prin BitTorrent
|
||||
GenericName[ro]=Client BitTorrent
|
||||
Name[ro]=qBittorrent
|
||||
Icon[ro]=qbittorrent
|
||||
Comment[ru]=Скачивайте и делитесь файлами с помощью BitTorrent
|
||||
GenericName[ru]=клиент BitTorrent
|
||||
Name[ru]=qBittorrent
|
||||
Icon[ru]=qbittorrent
|
||||
GenericName[sk]=Klient siete BitTorrent
|
||||
GenericName[sr]=BitTorrent-клијент
|
||||
Comment[sv]=Hämta och dela filer över BitTorrent
|
||||
GenericName[sv]=BitTorrent-klient
|
||||
Name[sv]=qBittorrent
|
||||
Icon[sv]=qbittorrent
|
||||
GenericName[tr]=BitTorrent istemcisi
|
||||
Comment[uk]=Завантажувати і обмінюватися файлами через BitTorrent
|
||||
GenericName[uk]=BitTorrent-клієнт
|
||||
Name[uk]=qBittorrent
|
||||
Icon[uk]=qbittorrent
|
||||
Comment[vi]=Tải về và chia sẻ các tập tin thông qua BitTorrent
|
||||
GenericName[vi]=Máy trạm dạng BitTorrent
|
||||
Name[vi]=qBittorrent
|
||||
Icon[vi]=qbittorrent
|
||||
Comment[zh_TW]=經由 BitTorrent 下載並分享檔案
|
||||
GenericName[zh_TW]=BitTorrent 客戶端
|
||||
Name[zh_TW]=qBittorrent
|
||||
Icon[zh_TW]=qbittorrent
|
||||
Comment[en_AU]=Download and share files over BitTorrent
|
||||
GenericName[en_AU]=BitTorrent client
|
||||
Name[en_AU]=qBittorrent
|
||||
Icon[en_AU]=qbittorrent
|
||||
|
||||
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 495 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 2.9 KiB |
@@ -1,83 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="32"
|
||||
height="32"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="qbittorrent_mono.svg">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="717"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="17.866666"
|
||||
inkscape:cx="15.004649"
|
||||
inkscape:cy="12.151033"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3030"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-49.656249,-638.375)"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3030">
|
||||
<path
|
||||
style="opacity:0.95;fill:none;stroke:#f5f5f5;stroke-width:2.09332085;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 79.602741,654.3166 c 0.353782,9.2059 -9.874651,16.51452 -18.469307,13.19706 -8.505573,-2.56766 -12.284789,-13.92871 -7.003202,-21.07663 4.900144,-7.80142 17.468596,-8.0676 22.694637,-0.48063 1.795761,2.39071 2.785631,5.37058 2.777872,8.3602 z"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="scale(0.9569639,1.0449715)"
|
||||
style="font-size:5.99402952px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#fafafa;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
id="text3757">
|
||||
<path
|
||||
d="m 65.221466,636.08054 0,-5.47891 c -0.295027,0.41443 -0.709458,0.75862 -1.243293,1.03256 -0.526826,0.27395 -1.088766,0.41092 -1.685821,0.41092 -1.327589,0 -2.472541,-0.53033 -3.43486,-1.59099 -0.9553,-1.06066 -1.432949,-2.51468 -1.432948,-4.36207 -10e-7,-1.12387 0.193166,-2.13185 0.579501,-3.02394 0.393356,-0.89207 0.958808,-1.5664 1.696357,-2.02298 0.744567,-0.46359 1.55938,-0.69539 2.44444,-0.6954 1.383772,10e-6 2.47253,0.58302 3.266279,1.74904 l 0,-1.49617 1.706893,0 0,15.47794 -1.896548,0 m -5.847692,-9.91473 c -2e-6,1.43998 0.30204,2.52171 0.906129,3.2452 0.604082,0.71648 1.327579,1.07472 2.170494,1.07472 0.807783,0 1.503184,-0.34068 2.086204,-1.02203 0.583005,-0.68838 0.874511,-1.73148 0.87452,-3.12931 -9e-6,-1.48913 -0.309076,-2.6095 -0.927202,-3.3611 -0.611117,-0.75159 -1.331103,-1.12739 -2.159958,-1.1274 -0.821843,10e-6 -1.520755,0.35122 -2.09674,1.05364 -0.568967,0.69541 -0.853449,1.78417 -0.853447,3.26628"
|
||||
style="font-size:21.57850838px;font-variant:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#fafafa;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="path2988" />
|
||||
<path
|
||||
d="m 71.84885,631.79224 -1.759576,0 0,-15.44634 1.896549,0 0,5.51053 c 0.80076,-1.00446 1.822788,-1.50669 3.066086,-1.5067 0.68837,10e-6 1.338113,0.14049 1.949231,0.42145 0.618125,0.27396 1.123871,0.6638 1.517239,1.16954 0.400372,0.49873 0.712951,1.10282 0.937738,1.81226 0.224765,0.70945 0.337153,1.46807 0.337164,2.27586 -1.1e-5,1.91762 -0.474148,3.39974 -1.422412,4.44635 -0.948283,1.04661 -2.086211,1.56992 -3.413787,1.56992 -1.320565,0 -2.356641,-0.5514 -3.108232,-1.65421 l 0,1.40134 m -0.02107,-5.67911 c -3e-6,1.34163 0.182627,2.31098 0.547892,2.90804 0.597057,0.97637 1.404845,1.46456 2.423367,1.46456 0.828855,0 1.545329,-0.35824 2.149422,-1.07472 0.604077,-0.72349 0.90612,-1.7982 0.906129,-3.22413 -9e-6,-1.46104 -0.291516,-2.53926 -0.87452,-3.23467 -0.575996,-0.69539 -1.274909,-1.04309 -2.09674,-1.0431 -0.828867,10e-6 -1.54534,0.36176 -2.149421,1.08525 -0.60409,0.71648 -0.906132,1.75607 -0.906129,3.11877"
|
||||
style="font-size:21.57850838px;font-variant:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#fafafa;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="path2990" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 538 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 3.1 KiB |
BIN
src/Icons/uparrow.png
Normal file
|
After Width: | Height: | Size: 787 B |
@@ -13,6 +13,10 @@
|
||||
<string>qBitTorrentDocument</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>BitTorrent Document</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/x-bittorrent</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSHandlerRank</key>
|
||||
@@ -36,59 +40,21 @@
|
||||
<string>BitTorrent Magnet URL</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleName</key>
|
||||
<string>qBittorrent</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>qbittorrent_mac.icns</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.1.10</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>2.6.9</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>qBit</string>
|
||||
<string>????</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>qbittorrent</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.qbittorrent</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<string>YES</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2006-2014 The qBittorrent project</string>
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
<string>public.item</string>
|
||||
<string>com.bittorrent.torrent</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>BitTorrent Document</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string>qBitTorrentDocument</string>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>org.bittorrent.torrent</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://www.bittorrent.org/beps/bep_0000.html</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>com.apple.ostype</key>
|
||||
<string>TORR</string>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>torrent</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/x-bittorrent</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NOTE</key>
|
||||
<string>This file was generated by Qt/QMake.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
426
src/about.ui
@@ -51,7 +51,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"><h3><b>qBittorrent</b></h3></string>
|
||||
<string><h3><b>qBittorrent</b></h3></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@@ -78,7 +78,7 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab6">
|
||||
<widget class="QWidget" name="tab2">
|
||||
<attribute name="title">
|
||||
<string>About</string>
|
||||
</attribute>
|
||||
@@ -89,7 +89,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="icons.qrc">:/Icons/skin/mascot.png</pixmap>
|
||||
<pixmap resource="../icons.qrc">:/Icons/skin/mascot.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -102,7 +102,13 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">A Bittorrent client programmed in C++, based on Qt4 toolkit </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">and libtorrent-rasterbar. <br /><br />Copyright ©2006-2010 Christophe Dumez<br /><br /></span><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">Home Page:</span><span style=" font-family:'DejaVu Sans';"> </span><a href="http://www.qbittorrent.org"><span style=" text-decoration: underline; color:#0000ff;">http://www.qbittorrent.org</span></a><span style=" font-family:'DejaVu Sans';"><br /></span><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">Forum:</span><span style=" font-family:'DejaVu Sans';"> </span><a href="http://forum.qbittorrent.org"><span style=" text-decoration: underline; color:#0000ff;">http://forum.qbittorrent.org</span></a></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">IRC:</span><span style=" font-family:'DejaVu Sans';"> #qbittorrent on Freenode</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@@ -123,7 +129,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab5">
|
||||
<widget class="QWidget" name="tab3">
|
||||
<attribute name="title">
|
||||
<string>Author</string>
|
||||
</attribute>
|
||||
@@ -134,16 +140,95 @@
|
||||
<item>
|
||||
<widget class="QFrame" name="te_authors">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -156,205 +241,6 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string notr="true">Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string notr="true">chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Greece</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string notr="true">sledgehammer999@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string notr="true">Sledgehammer999</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Current maintainer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Original author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -373,7 +259,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab3">
|
||||
<widget class="QWidget" name="tab5">
|
||||
<attribute name="title">
|
||||
<string>Translation</string>
|
||||
</attribute>
|
||||
@@ -390,7 +276,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab2">
|
||||
<widget class="QWidget" name="tab1">
|
||||
<attribute name="title">
|
||||
<string>License</string>
|
||||
</attribute>
|
||||
@@ -403,121 +289,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab1">
|
||||
<attribute name="title">
|
||||
<string>Libraries</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>This version of qBittorrent was built against the following libraries:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string notr="true">Qt:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string notr="true">Boost:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string notr="true">Libtorrent:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
|
||||
#include "ui_about.h"
|
||||
#include <QFile>
|
||||
#include <QtGlobal>
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
class about : public QDialog, private Ui::AboutDlg{
|
||||
Q_OBJECT
|
||||
@@ -45,31 +42,13 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
qDebug("Deleting about dlg");
|
||||
}
|
||||
|
||||
about(QWidget *parent): QDialog(parent) {
|
||||
about(QWidget *parent): QDialog(parent){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// About
|
||||
QString aboutText =
|
||||
QString::fromUtf8("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\"><html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; }</style></head><body style=\" font-size:11pt; font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("An advanced BitTorrent client programmed in C++, based on Qt4 toolkit and libtorrent-rasterbar.") +
|
||||
QString::fromUtf8(" <br /><br />") +
|
||||
trUtf8("Copyright ©2006-2013 The qBittorrent project") +
|
||||
QString::fromUtf8("<br /><br />") +
|
||||
tr("Home Page: ") +
|
||||
QString::fromUtf8("<a href=\"http://www.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://www.qbittorrent.org</span></a></p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("Bug Tracker: ") +
|
||||
QString::fromUtf8("<a href=\"http://bugs.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://bugs.qbittorrent.org</span></a><br />") +
|
||||
tr("Forum: ") +
|
||||
QString::fromUtf8(
|
||||
"<a href=\"http://forum.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://forum.qbittorrent.org</span></a></p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("IRC: #qbittorrent on Freenode") +
|
||||
QString::fromUtf8(
|
||||
"</p></body></html>");
|
||||
lb_about->setText(aboutText);
|
||||
// Set icons
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
||||
//Title
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
// Thanks
|
||||
QString thanks_txt;
|
||||
thanks_txt += QString::fromUtf8("<p>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</p>");
|
||||
@@ -80,57 +59,46 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
te_thanks->setHtml(thanks_txt);
|
||||
// Translation
|
||||
QString trans_txt = "<p>"+tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"</p>";
|
||||
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)</li>\
|
||||
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)</li>\
|
||||
<li><u>Armenian:</u> Hrant Ohanyan (hrantohanyan@mail.am)</li>\
|
||||
<li><u>Basque:</u> Xabier Aramendi (azpidatziak@gmail.com)</li>\
|
||||
<li><u>Belarusian:</u> Mihas Varantsou (meequz@gmail.com)</li>\
|
||||
<li><u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)</li>\
|
||||
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com) and 冥王歐西里斯 s8321414(Transifex)</li>\
|
||||
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)</li>\
|
||||
<li><u>Croatian:</u> Oliver Mucafir (oliver.untwist@gmail.com)</li>\
|
||||
<li><u>Czech:</u> Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex)</li>\
|
||||
<li><u>Czech:</u> Jirka Vilim (web@tets.cz)</li>\
|
||||
<li><u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)</li>\
|
||||
<li><u>Dutch:</u> Pieter Heyvaert (pieter_heyvaert@hotmail.com)</li>\
|
||||
<li><u>English(Australia):</u> Robert Readman readmanr(Transifex)</li>\
|
||||
<li><u>English(United Kingdom):</u> Robert Readman readmanr(Transifex)</li>\
|
||||
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net), Pekka Niemi (pekka.niemi@iki.fi) and Jiri Grönroos artnay(Transifex)</li>\
|
||||
<li><u>Galician:</u> Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex)</li>\
|
||||
<li><u>Georgian:</u> Beqa Arabuli (arabulibeqa@yahoo.com)</li>\
|
||||
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)</li>\
|
||||
<li><u>Galician:</u> Marcos Lans (marcoslansgarza@gmail.com)</li>\
|
||||
<li><u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)</li>\
|
||||
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net), Stephanos Antaris (santaris@csd.auth.gr), sledgehammer999(hammered999@gmail.com) and Γιάννης Ανθυμίδης Evropi(Transifex)</li>\
|
||||
<li><u>Hebrew:</u> David Deutsch (d.deffo@gmail.com)</li>\
|
||||
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)</li>\
|
||||
<li><u>Italian:</u> bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)</li>\
|
||||
<li><u>Japanese:</u> Masato Hashimoto (cabezon.hashimoto@gmail.com)</li>\
|
||||
<li><u>Italian:</u> Matteo Sechi (bu17714@gmail.com)</li>\
|
||||
<li><u>Japanese:</u> Nardog (alphisation@gmail.com)</li>\
|
||||
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
|
||||
<li><u>Lithuanian:</u> Naglis Jonaitis (njonaitis@gmail.com)</li>\
|
||||
<li><u>Norwegian:</u> Tomaso</li>\
|
||||
<li><u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)</li>\
|
||||
<li><u>Portuguese:</u> Sérgio Marques smarquespt(Transifex)</li>\
|
||||
<li><u>Portuguese(Brazil):</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex)</li>\
|
||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex)</li>\
|
||||
<li><u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)</li>\
|
||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
|
||||
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
|
||||
<li><u>Slovak:</u> helix84</li>\
|
||||
<li><u>Spanish:</u> Alfredo Monclús (alfrix), Francisco Luque Contreras (frannoe@ya.com) and José Antonio Moray moray33(Transifex)</li>\
|
||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se) and Emil Hammarberg Ooglogput(Transifex)</li>\
|
||||
<li><u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
|
||||
<li><u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)</li>\
|
||||
<li><u>Ukrainian:</u> Oleh Prypin (blaxpirit@gmail.com)</li>\
|
||||
<li><u>Vietnamese:</u> Anh Phan ppanhh(Transifex)</li></ul>");
|
||||
<li><u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)</li></ul>");
|
||||
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
|
||||
te_translation->setHtml(trans_txt);
|
||||
// License
|
||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
QFile licensefile(":/gpl.html");
|
||||
if (licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
if(licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
te_license->setHtml(licensefile.readAll());
|
||||
licensefile.close();
|
||||
}
|
||||
// Libraries
|
||||
label_11->setText(QT_VERSION_STR);
|
||||
label_12->setText(LIBTORRENT_VERSION);
|
||||
label_13->setText(QString::number(BOOST_VERSION / 100000) + "." + QString::number((BOOST_VERSION / 100) % 1000) + "." + QString::number(BOOST_VERSION % 100));
|
||||
show();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,699 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "addnewtorrentdialog.h"
|
||||
#include "ui_addnewtorrentdialog.h"
|
||||
#include "proplistdelegate.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "preferences.h"
|
||||
#include "qinisettings.h"
|
||||
#include "torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "messageboxraised.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
AddNewTorrentDialog::AddNewTorrentDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddNewTorrentDialog),
|
||||
m_contentModel(0),
|
||||
m_contentDelegate(0),
|
||||
m_isMagnet(false),
|
||||
m_hasMetadata(false),
|
||||
m_hasRenamedFile(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->lblMetaLoading->setVisible(false);
|
||||
ui->progMetaLoading->setVisible(false);
|
||||
|
||||
QIniSettings settings;
|
||||
Preferences pref;
|
||||
ui->start_torrent_cb->setChecked(!pref.addTorrentsInPause());
|
||||
ui->save_path_combo->addItem(fsutils::toDisplayPath(pref.getSavePath()), pref.getSavePath());
|
||||
loadSavePathHistory();
|
||||
ui->save_path_combo->insertSeparator(ui->save_path_combo->count());
|
||||
ui->save_path_combo->addItem(tr("Other...", "Other save path..."));
|
||||
connect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
|
||||
ui->default_save_path_cb->setVisible(false); // Default path is selected by default
|
||||
|
||||
// Load labels
|
||||
const QStringList customLabels = settings.value("TransferListFilters/customLabels", QStringList()).toStringList();
|
||||
ui->label_combo->addItem("");
|
||||
foreach (const QString& label, customLabels) {
|
||||
ui->label_combo->addItem(label);
|
||||
}
|
||||
ui->label_combo->model()->sort(0);
|
||||
ui->content_tree->header()->setSortIndicator(0, Qt::AscendingOrder);
|
||||
loadState();
|
||||
// Signal / slots
|
||||
connect(ui->adv_button, SIGNAL(clicked(bool)), SLOT(showAdvancedSettings(bool)));
|
||||
editHotkey = new QShortcut(QKeySequence("F2"), ui->content_tree, 0, 0, Qt::WidgetShortcut);
|
||||
connect(editHotkey, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
||||
connect(ui->content_tree, SIGNAL(doubleClicked(QModelIndex)), SLOT(renameSelectedFile()));
|
||||
}
|
||||
|
||||
AddNewTorrentDialog::~AddNewTorrentDialog()
|
||||
{
|
||||
saveState();
|
||||
delete ui;
|
||||
if (m_contentModel)
|
||||
delete m_contentModel;
|
||||
delete editHotkey;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::loadState()
|
||||
{
|
||||
QIniSettings settings;
|
||||
settings.beginGroup(QString::fromUtf8("AddNewTorrentDialog"));
|
||||
m_headerState = settings.value("treeHeaderState").toByteArray();
|
||||
int width = settings.value("width", -1).toInt();
|
||||
if (width >= 0) {
|
||||
QRect geo = geometry();
|
||||
geo.setWidth(width);
|
||||
setGeometry(geo);
|
||||
}
|
||||
ui->adv_button->setChecked(settings.value("expanded", false).toBool());
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveState()
|
||||
{
|
||||
QIniSettings settings;
|
||||
settings.beginGroup(QString::fromUtf8("AddNewTorrentDialog"));
|
||||
if (m_contentModel)
|
||||
settings.setValue("treeHeaderState", ui->content_tree->header()->saveState());
|
||||
settings.setValue("y", pos().y());
|
||||
settings.setValue("width", width());
|
||||
settings.setValue("expanded", ui->adv_button->isChecked());
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showTorrent(const QString &torrent_path, const QString& from_url, QWidget *parent)
|
||||
{
|
||||
AddNewTorrentDialog *dlg = new AddNewTorrentDialog(parent);
|
||||
if (dlg->loadTorrent(torrent_path, from_url))
|
||||
dlg->open();
|
||||
else
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showMagnet(const QString& link, QWidget *parent)
|
||||
{
|
||||
AddNewTorrentDialog *dlg = new AddNewTorrentDialog(parent);
|
||||
if (dlg->loadMagnet(link))
|
||||
dlg->open();
|
||||
else
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showEvent(QShowEvent *event) {
|
||||
QDialog::showEvent(event);
|
||||
Preferences pref;
|
||||
if (!pref.AdditionDialogFront())
|
||||
return;
|
||||
activateWindow();
|
||||
raise();
|
||||
}
|
||||
|
||||
|
||||
void AddNewTorrentDialog::showAdvancedSettings(bool show)
|
||||
{
|
||||
if (show) {
|
||||
ui->adv_button->setText(QString::fromUtf8("▲"));
|
||||
ui->settings_group->setVisible(true);
|
||||
ui->info_group->setVisible(true);
|
||||
if (m_hasMetadata && (m_torrentInfo->num_files() > 1)) {
|
||||
ui->content_tree->setVisible(true);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
} else {
|
||||
ui->content_tree->setVisible(false);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
}
|
||||
static_cast<QVBoxLayout*>(layout())->insertWidget(layout()->indexOf(ui->never_show_cb)+1, ui->adv_button);
|
||||
} else {
|
||||
ui->adv_button->setText(QString::fromUtf8("▼"));
|
||||
ui->settings_group->setVisible(false);
|
||||
ui->info_group->setVisible(false);
|
||||
ui->buttonsHLayout->insertWidget(0, layout()->takeAt(layout()->indexOf(ui->never_show_cb)+1)->widget());
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
}
|
||||
relayout();
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadTorrent(const QString& torrent_path, const QString& from_url)
|
||||
{
|
||||
m_isMagnet = false;
|
||||
m_url = from_url;
|
||||
if (torrent_path.startsWith("file://", Qt::CaseInsensitive))
|
||||
m_filePath = QUrl::fromEncoded(torrent_path.toLocal8Bit()).toLocalFile();
|
||||
else
|
||||
m_filePath = torrent_path;
|
||||
|
||||
if (!QFile::exists(m_filePath)) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), tr("The torrent file does not exist."));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasMetadata = true;
|
||||
|
||||
try {
|
||||
m_torrentInfo = new torrent_info(m_filePath.toUtf8().data());
|
||||
m_hash = misc::toQString(m_torrentInfo->info_hash());
|
||||
} catch(const std::exception& e) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Torrent is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);;
|
||||
return false;
|
||||
}
|
||||
|
||||
setupTreeview();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadMagnet(const QString &magnet_uri)
|
||||
{
|
||||
connect(QBtSession::instance(), SIGNAL(metadataReceivedHidden(const QTorrentHandle&)), SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
m_isMagnet = true;
|
||||
m_url = magnet_uri;
|
||||
m_hash = misc::magnetUriToHash(m_url);
|
||||
if (m_hash.isEmpty()) {
|
||||
MessageBoxRaised::critical(0, tr("Invalid magnet link"), tr("This magnet link was not recognized"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
MessageBoxRaised::information(0, tr("Already in download list"), tr("Magnet link is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set dialog title
|
||||
QString torrent_name = misc::magnetUriToName(m_url);
|
||||
setWindowTitle(torrent_name.isEmpty() ? tr("Magnet link") : torrent_name);
|
||||
|
||||
QIniSettings settings;
|
||||
setupTreeview();
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
|
||||
Preferences pref;
|
||||
// Override save path
|
||||
TorrentTempData::setSavePath(m_hash, QString(QDir::tempPath() + QDir::separator() + m_hash).replace("\\", "/"));
|
||||
HiddenData::addData(m_hash);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveSavePathHistory() const
|
||||
{
|
||||
QDir selected_save_path(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
QIniSettings settings;
|
||||
// Get current history
|
||||
QStringList history = settings.value("TorrentAdditionDlg/save_path_history").toStringList();
|
||||
QList<QDir> history_dirs;
|
||||
foreach(const QString dir, history)
|
||||
history_dirs << QDir(dir);
|
||||
if (!history_dirs.contains(selected_save_path)) {
|
||||
// Add save path to history
|
||||
history << selected_save_path.absolutePath();
|
||||
// Limit list size
|
||||
if (history.size() > 8)
|
||||
history.removeFirst();
|
||||
// Save history
|
||||
settings.setValue("TorrentAdditionDlg/save_path_history", history);
|
||||
}
|
||||
}
|
||||
|
||||
// save_path is a folder, not an absolute file path
|
||||
int AddNewTorrentDialog::indexOfSavePath(const QString &save_path)
|
||||
{
|
||||
QDir saveDir(save_path);
|
||||
for(int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
if (QDir(ui->save_path_combo->itemData(i).toString()) == saveDir)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateFileNameInSavePaths(const QString &new_filename)
|
||||
{
|
||||
for(int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
const QDir folder(ui->save_path_combo->itemData(i).toString());
|
||||
ui->save_path_combo->setItemText(i, fsutils::toDisplayPath(folder.absoluteFilePath(new_filename)));
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateDiskSpaceLabel() {
|
||||
// Determine torrent size
|
||||
qulonglong torrent_size = 0;
|
||||
|
||||
if (m_hasMetadata) {
|
||||
if (m_contentModel) {
|
||||
const std::vector<int> priorities = m_contentModel->model()->getFilesPriorities();
|
||||
Q_ASSERT(priorities.size() == (uint) m_torrentInfo->num_files());
|
||||
for (uint i=0; i<priorities.size(); ++i) {
|
||||
if (priorities[i] > 0)
|
||||
torrent_size += m_torrentInfo->file_at(i).size;
|
||||
}
|
||||
} else {
|
||||
torrent_size = m_torrentInfo->total_size();
|
||||
}
|
||||
}
|
||||
|
||||
QString size_string = torrent_size ? misc::friendlyUnit(torrent_size) : QString(tr("Not Available", "This size is unavailable."));
|
||||
size_string += " (";
|
||||
size_string += tr("Disk space: %1").arg(misc::friendlyUnit(fsutils::freeDiskSpaceOnPath(
|
||||
ui->save_path_combo->itemData(
|
||||
ui->save_path_combo->currentIndex()).toString())));
|
||||
size_string += ")";
|
||||
ui->size_lbl->setText(size_string);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::onSavePathChanged(int index)
|
||||
{
|
||||
static int old_index = 0;
|
||||
Preferences pref;
|
||||
|
||||
if (index == (ui->save_path_combo->count() - 1)) {
|
||||
disconnect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSavePathChanged(int)));
|
||||
// User is asking for a new save path
|
||||
QString cur_save_path = ui->save_path_combo->itemText(old_index);
|
||||
QString new_path, old_filename, new_filename;
|
||||
|
||||
if (m_torrentInfo && m_torrentInfo->num_files() == 1) {
|
||||
old_filename = fsutils::fileName(cur_save_path);
|
||||
new_path = QFileDialog::getSaveFileName(this, tr("Choose save path"), cur_save_path, QString(), 0, QFileDialog::DontConfirmOverwrite);
|
||||
if (!new_path.isEmpty())
|
||||
new_path = fsutils::branchPath(new_path, &new_filename);
|
||||
qDebug() << "new_path: " << new_path;
|
||||
qDebug() << "new_filename: " << new_filename;
|
||||
} else {
|
||||
if (!cur_save_path.isEmpty() && QDir(cur_save_path).exists())
|
||||
new_path = QFileDialog::getExistingDirectory(this, tr("Choose save path"), cur_save_path);
|
||||
else
|
||||
new_path = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
}
|
||||
if (!new_path.isEmpty()) {
|
||||
const int existing_index = indexOfSavePath(new_path);
|
||||
if (existing_index >= 0)
|
||||
ui->save_path_combo->setCurrentIndex(existing_index);
|
||||
else {
|
||||
// New path, prepend to combo box
|
||||
if (!new_filename.isEmpty())
|
||||
ui->save_path_combo->insertItem(0, fsutils::toDisplayPath(QDir(new_path).absoluteFilePath(new_filename)), new_path);
|
||||
else
|
||||
ui->save_path_combo->insertItem(0, fsutils::toDisplayPath(new_path), new_path);
|
||||
ui->save_path_combo->setCurrentIndex(0);
|
||||
}
|
||||
// Update file name in all save_paths
|
||||
if (!new_filename.isEmpty() && !fsutils::sameFileNames(old_filename, new_filename)) {
|
||||
m_hasRenamedFile = true;
|
||||
m_filesPath[0] = new_filename;
|
||||
updateFileNameInSavePaths(new_filename);
|
||||
}
|
||||
} else {
|
||||
// Restore index
|
||||
ui->save_path_combo->setCurrentIndex(old_index);
|
||||
}
|
||||
connect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
|
||||
}
|
||||
// Toggle default save path setting checkbox visibility
|
||||
ui->default_save_path_cb->setChecked(false);
|
||||
ui->default_save_path_cb->setVisible(QDir(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString()) != pref.getSavePath());
|
||||
relayout();
|
||||
// Remember index
|
||||
old_index = ui->save_path_combo->currentIndex();
|
||||
updateDiskSpaceLabel();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::relayout()
|
||||
{
|
||||
qApp->processEvents();
|
||||
int min_width = minimumWidth();
|
||||
setMinimumWidth(width());
|
||||
adjustSize();
|
||||
setMinimumWidth(min_width);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::renameSelectedFile()
|
||||
{
|
||||
const QModelIndexList selectedIndexes = ui->content_tree->selectionModel()->selectedRows(0);
|
||||
if (selectedIndexes.size() != 1)
|
||||
return;
|
||||
const QModelIndex &index = selectedIndexes.first();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
// Ask for new name
|
||||
bool ok;
|
||||
const QString new_name_last = AutoExpandableDialog::getText(this, tr("Rename the file"),
|
||||
tr("New name:"), QLineEdit::Normal,
|
||||
index.data().toString(), &ok).trimmed();
|
||||
if (ok && !new_name_last.isEmpty()) {
|
||||
if (!fsutils::isValidFileSystemName(new_name_last)) {
|
||||
MessageBoxRaised::warning(this, tr("The file could not be renamed"),
|
||||
tr("This file name contains forbidden characters, please choose a different one."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (m_contentModel->itemType(index) == TorrentContentModelItem::FileType) {
|
||||
// File renaming
|
||||
const int file_index = m_contentModel->getFileIndex(index);
|
||||
QString old_name = m_filesPath.at(file_index);
|
||||
old_name.replace("\\", "/");
|
||||
qDebug("Old name: %s", qPrintable(old_name));
|
||||
QStringList path_items = old_name.split("/");
|
||||
path_items.removeLast();
|
||||
path_items << new_name_last;
|
||||
QString new_name = path_items.join("/");
|
||||
if (fsutils::sameFileNames(old_name, new_name)) {
|
||||
qDebug("Name did not change");
|
||||
return;
|
||||
}
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("New name: %s", qPrintable(new_name));
|
||||
// Check if that name is already used
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
if (i == file_index) continue;
|
||||
if (fsutils::sameFileNames(m_filesPath.at(i), new_name)) {
|
||||
// Display error message
|
||||
MessageBoxRaised::warning(this, tr("The file could not be renamed"),
|
||||
tr("This name is already in use in this folder. Please use a different name."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("Renaming %s to %s", qPrintable(old_name), qPrintable(new_name));
|
||||
// Rename file in files_path
|
||||
m_filesPath.replace(file_index, new_name);
|
||||
m_hasRenamedFile = true;
|
||||
// Rename in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
} else {
|
||||
// Folder renaming
|
||||
QStringList path_items;
|
||||
path_items << index.data().toString();
|
||||
QModelIndex parent = m_contentModel->parent(index);
|
||||
while(parent.isValid()) {
|
||||
path_items.prepend(parent.data().toString());
|
||||
parent = m_contentModel->parent(parent);
|
||||
}
|
||||
const QString old_path = path_items.join("/");
|
||||
path_items.removeLast();
|
||||
path_items << new_name_last;
|
||||
QString new_path = path_items.join("/");
|
||||
if (!new_path.endsWith("/")) new_path += "/";
|
||||
// Check for overwriting
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
|
||||
if (current_name.startsWith(new_path, Qt::CaseSensitive)) {
|
||||
#else
|
||||
if (current_name.startsWith(new_path, Qt::CaseInsensitive)) {
|
||||
#endif
|
||||
MessageBoxRaised::warning(this, tr("The folder could not be renamed"),
|
||||
tr("This name is already in use in this folder. Please use a different name."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Replace path in all files
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
if (current_name.startsWith(old_path)) {
|
||||
QString new_name = current_name;
|
||||
new_name.replace(0, old_path.length(), new_path);
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("Rename %s to %s", qPrintable(current_name), qPrintable(new_name));
|
||||
// Rename in files_path
|
||||
m_filesPath.replace(i, new_name);
|
||||
}
|
||||
}
|
||||
m_hasRenamedFile = true;
|
||||
// Rename folder in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setdialogPosition()
|
||||
{
|
||||
qApp->processEvents();
|
||||
QPoint center(misc::screenCenter(this));
|
||||
// Adjust y
|
||||
QIniSettings settings;
|
||||
int y = settings.value("AddNewTorrentDialog/y", -1).toInt();
|
||||
if (y >= 0) {
|
||||
center.setY(y);
|
||||
} else {
|
||||
center.ry() -= 120;
|
||||
if (center.y() < 0)
|
||||
center.setY(0);
|
||||
}
|
||||
move(center);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::loadSavePathHistory()
|
||||
{
|
||||
QIniSettings settings;
|
||||
QDir default_save_path(Preferences().getSavePath());
|
||||
// Load save path history
|
||||
QStringList raw_path_history = settings.value("TorrentAdditionDlg/save_path_history").toStringList();
|
||||
foreach (const QString &sp, raw_path_history) {
|
||||
if (QDir(sp) != default_save_path)
|
||||
ui->save_path_combo->addItem(fsutils::toDisplayPath(sp), sp);
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::displayContentTreeMenu(const QPoint&) {
|
||||
QMenu myFilesLlistMenu;
|
||||
const QModelIndexList selectedRows = ui->content_tree->selectionModel()->selectedRows(0);
|
||||
QAction *actRename = 0;
|
||||
if (selectedRows.size() == 1 && m_torrentInfo->num_files() > 1) {
|
||||
actRename = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
myFilesLlistMenu.addSeparator();
|
||||
}
|
||||
QMenu subMenu;
|
||||
subMenu.setTitle(tr("Priority"));
|
||||
subMenu.addAction(ui->actionNot_downloaded);
|
||||
subMenu.addAction(ui->actionNormal);
|
||||
subMenu.addAction(ui->actionHigh);
|
||||
subMenu.addAction(ui->actionMaximum);
|
||||
myFilesLlistMenu.addMenu(&subMenu);
|
||||
// Call menu
|
||||
QAction *act = myFilesLlistMenu.exec(QCursor::pos());
|
||||
if (act) {
|
||||
if (act == actRename) {
|
||||
renameSelectedFile();
|
||||
} else {
|
||||
int prio = prio::NORMAL;
|
||||
if (act == ui->actionHigh)
|
||||
prio = prio::HIGH;
|
||||
else {
|
||||
if (act == ui->actionMaximum) {
|
||||
prio = prio::MAXIMUM;
|
||||
} else {
|
||||
if (act == ui->actionNot_downloaded)
|
||||
prio = prio::IGNORED;
|
||||
}
|
||||
}
|
||||
qDebug("Setting files priority");
|
||||
foreach (const QModelIndex &index, selectedRows) {
|
||||
qDebug("Setting priority(%d) for file at row %d", prio, index.row());
|
||||
m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), prio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::accept()
|
||||
{
|
||||
if (m_isMagnet)
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
|
||||
Preferences pref;
|
||||
// Save Temporary data about torrent
|
||||
QString save_path = ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString();
|
||||
TorrentTempData::setSavePath(m_hash, save_path);
|
||||
if (ui->skip_check_cb->isChecked()) {
|
||||
// TODO: Check if destination actually exists
|
||||
TorrentTempData::setSeedingMode(m_hash, true);
|
||||
}
|
||||
pref.addTorrentsInPause(!ui->start_torrent_cb->isChecked());
|
||||
|
||||
// Label
|
||||
const QString label = ui->label_combo->currentText();
|
||||
if (!label.isEmpty())
|
||||
TorrentTempData::setLabel(m_hash, label);
|
||||
|
||||
// Save file priorities
|
||||
if (m_contentModel)
|
||||
TorrentTempData::setFilesPriority(m_hash, m_contentModel->model()->getFilesPriorities());
|
||||
|
||||
// Rename files if necessary
|
||||
if (m_hasRenamedFile)
|
||||
TorrentTempData::setFilesPath(m_hash, m_filesPath);
|
||||
|
||||
// Add torrent
|
||||
if (m_isMagnet)
|
||||
QBtSession::instance()->unhideMagnet(m_hash);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);
|
||||
|
||||
saveSavePathHistory();
|
||||
// Save settings
|
||||
pref.useAdditionDialog(!ui->never_show_cb->isChecked());
|
||||
if (ui->default_save_path_cb->isChecked()) {
|
||||
pref.setSavePath(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
QBtSession::instance()->setDefaultSavePath(pref.getSavePath());
|
||||
}
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::reject() {
|
||||
if (m_isMagnet) {
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
setMetadataProgressIndicator(false);
|
||||
QBtSession::instance()->deleteTorrent(m_hash, true);
|
||||
}
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateMetadata(const QTorrentHandle &h) {
|
||||
try {
|
||||
if (h.hash() != m_hash)
|
||||
return;
|
||||
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
Q_ASSERT(h.has_metadata());
|
||||
|
||||
m_torrentInfo = new torrent_info(h.get_torrent_info());
|
||||
|
||||
// Good to go
|
||||
m_hasMetadata = true;
|
||||
setMetadataProgressIndicator(true, tr("Parsing metadata..."));
|
||||
|
||||
// Update UI
|
||||
setupTreeview();
|
||||
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
||||
} catch (invalid_handle&) {
|
||||
MessageBoxRaised::critical(0, tr("I/O Error"), ("Unknown error."));
|
||||
setMetadataProgressIndicator(false, tr("Unknown error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText) {
|
||||
// Always show info label when waiting for metadata
|
||||
ui->lblMetaLoading->setVisible(true);
|
||||
ui->lblMetaLoading->setText(labelText);
|
||||
ui->progMetaLoading->setVisible(visibleIndicator);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setupTreeview() {
|
||||
if (!m_hasMetadata) {
|
||||
ui->comment_lbl->setText(tr("Not Available", "This comment is unavailable"));
|
||||
ui->date_lbl->setText(tr("Not Available", "This date is unavailable"));
|
||||
}
|
||||
else {
|
||||
// Set dialog title
|
||||
setWindowTitle(misc::toQStringU(m_torrentInfo->name()));
|
||||
|
||||
// Set torrent information
|
||||
QString comment = misc::toQString(m_torrentInfo->comment());
|
||||
ui->comment_lbl->setText(comment.replace('\n', ' '));
|
||||
ui->date_lbl->setText(m_torrentInfo->creation_date() ? misc::toQString(*m_torrentInfo->creation_date()) : tr("Not available"));
|
||||
|
||||
file_storage fs = m_torrentInfo->files();
|
||||
|
||||
// Populate m_filesList
|
||||
for (int i = 0; i < m_torrentInfo->num_files(); ++i) {
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
m_filesPath << misc::toQStringU(fs.file_path(m_torrentInfo->file_at(i)));
|
||||
#else
|
||||
m_filesPath << misc::toQStringU(m_torrentInfo->file_at(i).path.string());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare content tree
|
||||
if (fs.num_files() > 1) {
|
||||
m_contentModel = new TorrentContentFilterModel(this);
|
||||
connect(m_contentModel->model(), SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabel()));
|
||||
ui->content_tree->setModel(m_contentModel);
|
||||
ui->content_tree->hideColumn(PROGRESS);
|
||||
m_contentDelegate = new PropListDelegate();
|
||||
ui->content_tree->setItemDelegate(m_contentDelegate);
|
||||
connect(ui->content_tree, SIGNAL(clicked(const QModelIndex&)), ui->content_tree, SLOT(edit(const QModelIndex&)));
|
||||
connect(ui->content_tree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContentTreeMenu(const QPoint&)));
|
||||
|
||||
// List files in torrent
|
||||
m_contentModel->model()->setupModelData(*m_torrentInfo);
|
||||
if (!m_headerState.isEmpty())
|
||||
ui->content_tree->header()->restoreState(m_headerState);
|
||||
|
||||
// Expand root folder
|
||||
ui->content_tree->setExpanded(m_contentModel->index(0, 0), true);
|
||||
} else {
|
||||
// Update save paths (append file name to them)
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
QString single_file_relpath = misc::toQStringU(fs.file_path(m_torrentInfo->file_at(0)));
|
||||
#else
|
||||
QString single_file_relpath = misc::toQStringU(m_torrentInfo->file_at(0).path.string());
|
||||
#endif
|
||||
for (int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
ui->save_path_combo->setItemText(i, fsutils::toDisplayPath(QDir(ui->save_path_combo->itemText(i)).absoluteFilePath(single_file_relpath)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QIniSettings settings;
|
||||
updateDiskSpaceLabel();
|
||||
showAdvancedSettings(settings.value("AddNewTorrentDialog/expanded").toBool());
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef ADDNEWTORRENTDIALOG_H
|
||||
#define ADDNEWTORRENTDIALOG_H
|
||||
|
||||
#include <QShortcut>
|
||||
#include <QDialog>
|
||||
#include <QUrl>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class AddNewTorrentDialog;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class TorrentContentFilterModel;
|
||||
class PropListDelegate;
|
||||
|
||||
class AddNewTorrentDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~AddNewTorrentDialog();
|
||||
|
||||
static void showTorrent(const QString& torrent_path, const QString& from_url, QWidget *parent = 0);
|
||||
static void showMagnet(const QString& torrent_link, QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
|
||||
private slots:
|
||||
void showAdvancedSettings(bool show);
|
||||
void displayContentTreeMenu(const QPoint&);
|
||||
void updateDiskSpaceLabel();
|
||||
void onSavePathChanged(int);
|
||||
void relayout();
|
||||
void renameSelectedFile();
|
||||
void setdialogPosition();
|
||||
void updateMetadata(const QTorrentHandle& h);
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
virtual void reject();
|
||||
|
||||
private:
|
||||
explicit AddNewTorrentDialog(QWidget *parent = 0);
|
||||
bool loadTorrent(const QString& torrent_path, const QString& from_url);
|
||||
bool loadMagnet(const QString& magnet_uri);
|
||||
void loadSavePathHistory();
|
||||
void saveSavePathHistory() const;
|
||||
int indexOfSavePath(const QString& save_path);
|
||||
void updateFileNameInSavePaths(const QString& new_filename);
|
||||
void loadState();
|
||||
void saveState();
|
||||
void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = QString());
|
||||
void setupTreeview();
|
||||
|
||||
private:
|
||||
Ui::AddNewTorrentDialog *ui;
|
||||
TorrentContentFilterModel *m_contentModel;
|
||||
PropListDelegate *m_contentDelegate;
|
||||
bool m_isMagnet;
|
||||
bool m_hasMetadata;
|
||||
QString m_filePath;
|
||||
QString m_url;
|
||||
QString m_hash;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> m_torrentInfo;
|
||||
QStringList m_filesPath;
|
||||
bool m_hasRenamedFile;
|
||||
QShortcut *editHotkey;
|
||||
QByteArray m_headerState;
|
||||
};
|
||||
|
||||
#endif // ADDNEWTORRENTDIALOG_H
|
||||
@@ -1,300 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AddNewTorrentDialog</class>
|
||||
<widget class="QDialog" name="AddNewTorrentDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>414</width>
|
||||
<height>590</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Save as</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="save_path_combo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="default_save_path_cb">
|
||||
<property name="text">
|
||||
<string>Set as default save path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="never_show_cb">
|
||||
<property name="text">
|
||||
<string>Never show again</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="adv_button">
|
||||
<property name="text">
|
||||
<string notr="true">▼</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="settings_group">
|
||||
<property name="title">
|
||||
<string>Torrent settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3" columnstretch="1,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="start_torrent_cb">
|
||||
<property name="text">
|
||||
<string>Start torrent</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Label:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="label_combo">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertAtTop</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="skip_check_cb">
|
||||
<property name="text">
|
||||
<string>Skip hash check</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="info_group">
|
||||
<property name="title">
|
||||
<string>Torrent Information</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="size_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">xx GB (xx GB available)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Comment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="comment_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">comment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Date:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="date_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">02/03/2012 20:30</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="content_tree">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="buttonsHLayout">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progMetaLoading">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string notr="true">%p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblMetaLoading">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionNormal">
|
||||
<property name="text">
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHigh">
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMaximum">
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNot_downloaded">
|
||||
<property name="text">
|
||||
<string>Do not download</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AddNewTorrentDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AddNewTorrentDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2013 Nick Tiskov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : daymansmail@gmail.com
|
||||
*/
|
||||
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "ui_autoexpandabledialog.h"
|
||||
|
||||
AutoExpandableDialog::AutoExpandableDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AutoExpandableDialog) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AutoExpandableDialog::~AutoExpandableDialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString AutoExpandableDialog::getText(QWidget *parent, const QString &title, const QString &label,
|
||||
QLineEdit::EchoMode mode, const QString &text, bool *ok,
|
||||
Qt::InputMethodHints inputMethodHints) {
|
||||
|
||||
AutoExpandableDialog d(parent);
|
||||
d.setWindowTitle(title);
|
||||
d.ui->textLabel->setText(label);
|
||||
d.ui->textEdit->setText(text);
|
||||
d.ui->textEdit->setEchoMode(mode);
|
||||
d.ui->textEdit->setInputMethodHints(inputMethodHints);
|
||||
|
||||
bool res = d.exec();
|
||||
if (ok)
|
||||
*ok = res;
|
||||
|
||||
if (!res)
|
||||
return QString();
|
||||
|
||||
return d.ui->textEdit->text();
|
||||
}
|
||||
|
||||
void AutoExpandableDialog::showEvent(QShowEvent *e) {
|
||||
// Overriding showEvent is required for consistent UI with fixed size under custom DPI
|
||||
// Show dialog
|
||||
QDialog::showEvent(e);
|
||||
// and resize textbox to fit the text
|
||||
|
||||
// NOTE: For some strange reason QFontMetrics gets more accurate
|
||||
// when called from showEvent. Only 6 symbols off instead of 11 symbols off.
|
||||
int textW = ui->textEdit->fontMetrics().width(ui->textEdit->text()) + 4;
|
||||
int screenW = QApplication::desktop()->width() / 4;
|
||||
int wd = textW;
|
||||
|
||||
if (!windowTitle().isEmpty()) {
|
||||
int _w = fontMetrics().width(windowTitle());
|
||||
if (_w > wd)
|
||||
wd = _w;
|
||||
}
|
||||
|
||||
if (!ui->textLabel->text().isEmpty()) {
|
||||
int _w = ui->textLabel->fontMetrics().width(ui->textLabel->text());
|
||||
if (_w > wd)
|
||||
wd = _w;
|
||||
}
|
||||
|
||||
|
||||
// Now resize the dialog to fit the contents
|
||||
// Maximum value is whichever is smaller:
|
||||
// 1. screen width / 4
|
||||
// 2. max width of text from either of: label, title, textedit
|
||||
// If the value is less than dialog default size default size is used
|
||||
wd = textW < screenW ? textW : screenW;
|
||||
if (wd > width())
|
||||
resize(width() - ui->horizontalLayout->sizeHint().width() + wd, height());
|
||||
|
||||
// Use old dialog behavior: prohibit resizing the dialog
|
||||
setFixedHeight(height());
|
||||
|
||||
// Update geometry: center on screen
|
||||
QDesktopWidget *desk = QApplication::desktop();
|
||||
MainWindow *wnd = qobject_cast<MainWindow*>(QApplication::activeWindow());
|
||||
QPoint p = QCursor::pos();
|
||||
|
||||
int screenNum = 0;
|
||||
if (wnd == 0)
|
||||
screenNum = desk->screenNumber(p);
|
||||
else if (!wnd->isHidden())
|
||||
screenNum = desk->screenNumber(wnd);
|
||||
else
|
||||
screenNum = desk->screenNumber(p);
|
||||
|
||||
QRect screenRes = desk->screenGeometry(screenNum);
|
||||
|
||||
QRect geom = geometry();
|
||||
geom.moveCenter(QPoint(screenRes.width() / 2, screenRes.height() / 2));
|
||||
setGeometry(geom);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2013 Nick Tiskov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : daymansmail@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef AUTOEXPANDABLEDIALOG_H
|
||||
#define AUTOEXPANDABLEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace Ui {
|
||||
class AutoExpandableDialog;
|
||||
}
|
||||
|
||||
class AutoExpandableDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AutoExpandableDialog(QWidget *parent = 0);
|
||||
~AutoExpandableDialog();
|
||||
|
||||
static QString getText(QWidget *parent, const QString& title, const QString& label,
|
||||
QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(),
|
||||
bool * ok = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *e);
|
||||
|
||||
private:
|
||||
Ui::AutoExpandableDialog *ui;
|
||||
};
|
||||
|
||||
#endif // AUTOEXPANDABLEDIALOG_H
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AutoExpandableDialog</class>
|
||||
<widget class="QDialog" name="AutoExpandableDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>222</width>
|
||||
<height>94</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textEdit">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AutoExpandableDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AutoExpandableDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -44,7 +44,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">deletion message goes here</string>
|
||||
<string>Are you sure you want to delete the selected torrents from the transfer list?</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
|
||||
@@ -40,12 +40,8 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DeletionConfirmationDlg(QWidget *parent, const int &size, const QString &name): QDialog(parent) {
|
||||
DeletionConfirmationDlg(QWidget *parent=0): QDialog(parent) {
|
||||
setupUi(this);
|
||||
if (size == 1)
|
||||
label->setText(tr("Are you sure you want to delete \"%1\" from the transfer list?", "Are you sure you want to delete \"ubuntu-linux-iso\" from the transfer list?").arg(name));
|
||||
else
|
||||
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
||||
// Icons
|
||||
lbl_warn->setPixmap(IconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height()));
|
||||
lbl_warn->setFixedWidth(lbl_warn->height());
|
||||
@@ -61,10 +57,10 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
return checkPermDelete->isChecked();
|
||||
}
|
||||
|
||||
static bool askForDeletionConfirmation(bool& delete_local_files, const int& size, const QString& name) {
|
||||
DeletionConfirmationDlg dlg(NULL, size, name);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
delete_local_files = dlg.shouldDeleteLocalFiles();
|
||||
static bool askForDeletionConfirmation(bool *delete_local_files) {
|
||||
DeletionConfirmationDlg dlg;
|
||||
if(dlg.exec() == QDialog::Accepted) {
|
||||
*delete_local_files = dlg.shouldDeleteLocalFiles();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include "dnsupdater.h"
|
||||
#include "qbtsession.h"
|
||||
|
||||
DNSUpdater::DNSUpdater(QObject *parent) :
|
||||
QObject(parent), m_state(OK), m_service(DNS::NONE)
|
||||
{
|
||||
updateCredentials();
|
||||
|
||||
// Load saved settings from previous session
|
||||
QIniSettings settings;
|
||||
m_lastIPCheckTime = settings.value("DNSUpdater/lastUpdateTime").toDateTime();
|
||||
m_lastIP = QHostAddress(settings.value("DNSUpdater/lastIP").toString());
|
||||
|
||||
// Start IP checking timer
|
||||
m_ipCheckTimer.setInterval(IP_CHECK_INTERVAL_MS);
|
||||
connect(&m_ipCheckTimer, SIGNAL(timeout()), SLOT(checkPublicIP()));
|
||||
m_ipCheckTimer.start();
|
||||
|
||||
// Check lastUpdate to avoid flooding
|
||||
if (!m_lastIPCheckTime.isValid() ||
|
||||
m_lastIPCheckTime.secsTo(QDateTime::currentDateTime())*1000 > IP_CHECK_INTERVAL_MS) {
|
||||
checkPublicIP();
|
||||
}
|
||||
}
|
||||
|
||||
DNSUpdater::~DNSUpdater() {
|
||||
// Save lastupdate time and last ip
|
||||
QIniSettings settings;
|
||||
settings.setValue("DNSUpdater/lastUpdateTime", m_lastIPCheckTime);
|
||||
settings.setValue("DNSUpdater/lastIP", m_lastIP.toString());
|
||||
}
|
||||
|
||||
void DNSUpdater::checkPublicIP()
|
||||
{
|
||||
Q_ASSERT(m_state == OK);
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||
SLOT(ipRequestFinished(QNetworkReply*)));
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl("http://checkip.dyndns.org"));
|
||||
request.setRawHeader("User-Agent", "qBittorrent/"VERSION" chris@qbittorrent.org");
|
||||
manager->get(request);
|
||||
}
|
||||
|
||||
void DNSUpdater::ipRequestFinished(QNetworkReply *reply)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (reply->error()) {
|
||||
// Error
|
||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||
} else {
|
||||
// Parse response
|
||||
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
|
||||
QString ret = reply->readAll();
|
||||
if (ipregex.indexIn(ret) >= 0) {
|
||||
QString ip_str = ipregex.cap(1);
|
||||
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ip_str;
|
||||
QHostAddress new_ip(ip_str);
|
||||
if (!new_ip.isNull()) {
|
||||
if (m_lastIP != new_ip) {
|
||||
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
|
||||
qDebug() << m_lastIP.toString() << "->" << new_ip.toString();
|
||||
m_lastIP = new_ip;
|
||||
updateDNSService();
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to construct a QHostAddress from the IP string";
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Regular expression failed ot capture the IP address";
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
reply->deleteLater();
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void DNSUpdater::updateDNSService()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// Prepare request
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||
SLOT(ipUpdateFinished(QNetworkReply*)));
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(getUpdateUrl());
|
||||
request.setRawHeader("User-Agent", "qBittorrent/"VERSION" chris@qbittorrent.org");
|
||||
manager->get(request);
|
||||
}
|
||||
|
||||
QUrl DNSUpdater::getUpdateUrl() const
|
||||
{
|
||||
QUrl url;
|
||||
#ifdef QT_NO_OPENSSL
|
||||
url.setScheme("http");
|
||||
#else
|
||||
url.setScheme("https");
|
||||
#endif
|
||||
url.setUserName(m_username);
|
||||
url.setPassword(m_password);
|
||||
|
||||
Q_ASSERT(!m_lastIP.isNull());
|
||||
// Service specific
|
||||
switch(m_service) {
|
||||
case DNS::DYNDNS:
|
||||
url.setHost("members.dyndns.org");
|
||||
break;
|
||||
case DNS::NOIP:
|
||||
url.setHost("dynupdate.no-ip.com");
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Unrecognized Dynamic DNS service!";
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
url.setPath("/nic/update");
|
||||
url.addQueryItem("hostname", m_domain);
|
||||
url.addQueryItem("myip", m_lastIP.toString());
|
||||
Q_ASSERT(url.isValid());
|
||||
qDebug() << Q_FUNC_INFO << url.toString();
|
||||
return url;
|
||||
}
|
||||
|
||||
void DNSUpdater::ipUpdateFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (reply->error()) {
|
||||
// Error
|
||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||
} else {
|
||||
// Pase reply
|
||||
processIPUpdateReply(reply->readAll());
|
||||
}
|
||||
// Clean up
|
||||
reply->deleteLater();
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void DNSUpdater::processIPUpdateReply(const QString &reply)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << reply;
|
||||
QString code = reply.split(" ").first();
|
||||
qDebug() << Q_FUNC_INFO << "Code:" << code;
|
||||
if (code == "good" || code == "nochg") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Your dynamic DNS was successfully updated."), "green");
|
||||
return;
|
||||
}
|
||||
if (code == "911" || code == "dnserr") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
// It will retry in 30 minutes because the timer was not stopped
|
||||
return;
|
||||
}
|
||||
// Everything bellow is an error, stop updating until the user updates something
|
||||
m_ipCheckTimer.stop();
|
||||
m_lastIP.clear();
|
||||
if (code == "nohost") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: hostname supplied does not exist under specified account."),
|
||||
"red");
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
if (code == "badauth") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Invalid username/password."), "red");
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
if (code == "badagent") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
if (code == "!donator") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: %1 was returned by the service, please report a bug at http://bugs.qbittorrent.org.").arg("!donator"),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
if (code == "abuse") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DNSUpdater::updateCredentials()
|
||||
{
|
||||
if (m_state == FATAL) return;
|
||||
Preferences pref;
|
||||
bool change = false;
|
||||
// Get DNS service information
|
||||
if (m_service != pref.getDynDNSService()) {
|
||||
m_service = pref.getDynDNSService();
|
||||
change = true;
|
||||
}
|
||||
if (m_domain != pref.getDynDomainName()) {
|
||||
m_domain = pref.getDynDomainName();
|
||||
QRegExp domain_regex("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$");
|
||||
if (domain_regex.indexIn(m_domain) < 0) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied domain name is invalid."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
if (m_username != pref.getDynDNSUsername()) {
|
||||
m_username = pref.getDynDNSUsername();
|
||||
if (m_username.length() < 4) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied username is too short."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
if (m_password != pref.getDynDNSPassword()) {
|
||||
m_password = pref.getDynDNSPassword();
|
||||
if (m_password.length() < 4) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied password is too short."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
|
||||
if (m_state == INVALID_CREDS && change) {
|
||||
m_state = OK; // Try again
|
||||
m_ipCheckTimer.start();
|
||||
checkPublicIP();
|
||||
}
|
||||
}
|
||||
|
||||
QUrl DNSUpdater::getRegistrationUrl(int service)
|
||||
{
|
||||
switch(service) {
|
||||
case DNS::DYNDNS:
|
||||
return QUrl("https://www.dyndns.com/account/services/hosts/add.html");
|
||||
case DNS::NOIP:
|
||||
return QUrl("http://www.no-ip.com/services/managed_dns/free_dynamic_dns.html");
|
||||
default:
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
return QUrl();
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef DNSUPDATER_H
|
||||
#define DNSUPDATER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkReply>
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
#include "preferences.h"
|
||||
|
||||
/*!
|
||||
* Based on http://www.dyndns.com/developers/specs/
|
||||
*/
|
||||
class DNSUpdater : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DNSUpdater(QObject *parent = 0);
|
||||
~DNSUpdater();
|
||||
static QUrl getRegistrationUrl(int service);
|
||||
|
||||
public slots:
|
||||
void updateCredentials();
|
||||
|
||||
private slots:
|
||||
void checkPublicIP();
|
||||
void ipRequestFinished(QNetworkReply* reply);
|
||||
void updateDNSService();
|
||||
void ipUpdateFinished(QNetworkReply* reply);
|
||||
|
||||
private:
|
||||
QUrl getUpdateUrl() const;
|
||||
void processIPUpdateReply(const QString &reply);
|
||||
|
||||
private:
|
||||
QHostAddress m_lastIP;
|
||||
QDateTime m_lastIPCheckTime;
|
||||
QTimer m_ipCheckTimer;
|
||||
int m_state;
|
||||
// Service creds
|
||||
DNS::Service m_service;
|
||||
QString m_domain;
|
||||
QString m_username;
|
||||
QString m_password;
|
||||
|
||||
private:
|
||||
static const int IP_CHECK_INTERVAL_MS = 1800000; // 30 min
|
||||
enum State { OK, INVALID_CREDS, FATAL };
|
||||
};
|
||||
|
||||
#endif // DNSUPDATER_H
|
||||
@@ -43,65 +43,47 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
downloadFromURL(QWidget *parent): QDialog(parent) {
|
||||
downloadFromURL(QWidget *parent): QDialog(parent){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setModal(true);
|
||||
show();
|
||||
// Paste clipboard if there is an URL in it
|
||||
QString clip_txt = qApp->clipboard()->text();
|
||||
QStringList clip_txt_list = clip_txt.split(QString::fromUtf8("\n"));
|
||||
clip_txt.clear();
|
||||
QStringList clip_txt_list_cleaned;
|
||||
foreach (clip_txt, clip_txt_list) {
|
||||
clip_txt = clip_txt.trimmed();
|
||||
if (!clip_txt.isEmpty()) {
|
||||
if (clip_txt_list_cleaned.indexOf(QRegExp(clip_txt, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) {
|
||||
if (clip_txt.startsWith("http://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("https://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("ftp://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("magnet:", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)
|
||||
|| (clip_txt.size() == 40 && !clip_txt.contains(QRegExp("[^0-9A-Fa-f]")))
|
||||
|| (clip_txt.size() == 32 && !clip_txt.contains(QRegExp("[^2-7A-Za-z]")))) {
|
||||
clip_txt_list_cleaned << clip_txt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive) || clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
textUrls->setText(clip_txt);
|
||||
}
|
||||
if (clip_txt_list_cleaned.size() > 0)
|
||||
textUrls->setText(clip_txt_list_cleaned.join("\n"));
|
||||
}
|
||||
|
||||
~downloadFromURL() {}
|
||||
~downloadFromURL(){}
|
||||
|
||||
signals:
|
||||
void urlsReadyToBeDownloaded(const QStringList& torrent_urls);
|
||||
|
||||
public slots:
|
||||
void on_downloadButton_clicked() {
|
||||
close();
|
||||
void on_downloadButton_clicked(){
|
||||
QString urls = textUrls->toPlainText();
|
||||
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
||||
QString url;
|
||||
QStringList url_list_cleaned;
|
||||
foreach (url, url_list) {
|
||||
foreach(url, url_list){
|
||||
url = url.trimmed();
|
||||
if (!url.isEmpty()) {
|
||||
if (url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) {
|
||||
if(!url.isEmpty()){
|
||||
if(url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0){
|
||||
url_list_cleaned << url;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!url_list_cleaned.size()) {
|
||||
if(!url_list_cleaned.size()){
|
||||
QMessageBox::critical(0, tr("No URL entered"), tr("Please type at least one URL."));
|
||||
return;
|
||||
}
|
||||
emit urlsReadyToBeDownloaded(url_list_cleaned);
|
||||
qDebug("Emitted urlsReadytobedownloaded signal");
|
||||
close();
|
||||
}
|
||||
|
||||
void on_cancelButton_clicked() {
|
||||
void on_cancelButton_clicked(){
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,14 +14,31 @@
|
||||
<string>Download from urls</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadURL_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
@@ -48,16 +65,28 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>true</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>One per line (HTTP links, Magnet links and info-hashes are supported)</string>
|
||||
<string>Both HTTP and Magnet links are supported</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkCookieJar>
|
||||
|
||||
#include "downloadthread.h"
|
||||
@@ -40,72 +41,21 @@
|
||||
#include "rsssettings.h"
|
||||
#endif
|
||||
#include "qinisettings.h"
|
||||
#include <zlib.h>
|
||||
|
||||
/** Download Thread **/
|
||||
|
||||
DownloadThread::DownloadThread(QObject* parent) : QObject(parent) {
|
||||
downloadThread::downloadThread(QObject* parent) : QObject(parent) {
|
||||
connect(&m_networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
|
||||
#ifndef QT_NO_OPENSSL
|
||||
connect(&m_networkManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
#endif
|
||||
}
|
||||
|
||||
QByteArray DownloadThread::gUncompress(Bytef *inData, size_t len) {
|
||||
if (len <= 4) {
|
||||
qWarning("gUncompress: Input data is truncated");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray result;
|
||||
|
||||
z_stream strm;
|
||||
static const int CHUNK_SIZE = 1024;
|
||||
char out[CHUNK_SIZE];
|
||||
|
||||
/* allocate inflate state */
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = len;
|
||||
strm.next_in = inData;
|
||||
|
||||
const int windowBits = 15;
|
||||
const int ENABLE_ZLIB_GZIP = 32;
|
||||
|
||||
int ret = inflateInit2(&strm, windowBits|ENABLE_ZLIB_GZIP ); // gzip decoding
|
||||
if (ret != Z_OK)
|
||||
return QByteArray();
|
||||
|
||||
// run inflate()
|
||||
do {
|
||||
strm.avail_out = CHUNK_SIZE;
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(out);
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
||||
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
(void) inflateEnd(&strm);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
result.append(out, CHUNK_SIZE - strm.avail_out);
|
||||
} while (!strm.avail_out);
|
||||
|
||||
// clean up and return
|
||||
inflateEnd(&strm);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
void downloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
QString url = reply->url().toString();
|
||||
qDebug("Download finished: %s", qPrintable(url));
|
||||
// Check if the request was successful
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
if(reply->error() != QNetworkReply::NoError) {
|
||||
// Failure
|
||||
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
|
||||
emit downloadFailure(url, errorCodeToString(reply->error()));
|
||||
@@ -114,54 +64,36 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
}
|
||||
// Check if the server ask us to redirect somewhere lese
|
||||
const QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (redirection.isValid()) {
|
||||
if(redirection.isValid()) {
|
||||
// We should redirect
|
||||
QUrl newUrl = redirection.toUrl();
|
||||
// Resolve relative urls
|
||||
if (newUrl.isRelative())
|
||||
newUrl = reply->url().resolved(newUrl);
|
||||
const QString newUrlString = newUrl.toString();
|
||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString));
|
||||
// Redirect to magnet workaround
|
||||
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
qDebug("Magnet redirect detected.");
|
||||
reply->abort();
|
||||
emit magnetRedirect(newUrlString, url);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
m_redirectMapping.insert(newUrlString, url);
|
||||
// redirecting with first cookies
|
||||
downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url));
|
||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(redirection.toUrl().toString()));
|
||||
m_redirectMapping.insert(redirection.toUrl().toString(), url);
|
||||
downloadUrl(redirection.toUrl().toString());
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
// Checking if it was redirected, restoring initial URL
|
||||
if (m_redirectMapping.contains(url)) {
|
||||
if(m_redirectMapping.contains(url)) {
|
||||
url = m_redirectMapping.take(url);
|
||||
}
|
||||
// Success
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
tmpfile->setAutoRemove(false);
|
||||
if (tmpfile->open()) {
|
||||
tmpfile->setAutoRemove(false);
|
||||
QString filePath = tmpfile->fileName();
|
||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||
if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
|
||||
QByteArray replyData = reply->readAll();
|
||||
if (reply->rawHeader("Content-Encoding") == "gzip") {
|
||||
// uncompress gzip reply
|
||||
replyData = gUncompress(reinterpret_cast<unsigned char*>(replyData.data()), replyData.length());
|
||||
}
|
||||
tmpfile->write(replyData);
|
||||
if(reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
|
||||
// TODO: Support GZIP compression
|
||||
tmpfile->write(reply->readAll());
|
||||
tmpfile->close();
|
||||
// XXX: tmpfile needs to be deleted on Windows before using the file
|
||||
// or it will complain that the file is used by another process.
|
||||
// XXX: For some reason, tmpfile has to be destroyed before
|
||||
// the signal is sent or the file stays locked on Windows
|
||||
// for some reason.
|
||||
delete tmpfile;
|
||||
// Send finished signal
|
||||
emit downloadFinished(url, filePath);
|
||||
} else {
|
||||
delete tmpfile;
|
||||
fsutils::forceRemove(filePath);
|
||||
// Error when reading the request
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
}
|
||||
@@ -173,21 +105,39 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void DownloadThread::downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& cookies)
|
||||
{
|
||||
#ifndef DISABLE_GUI
|
||||
void downloadThread::loadCookies(const QString &host_name, QString url) {
|
||||
const QList<QByteArray> raw_cookies = RssSettings().getHostNameCookies(host_name);
|
||||
QNetworkCookieJar *cookie_jar = m_networkManager.cookieJar();
|
||||
QList<QNetworkCookie> cookies;
|
||||
qDebug("Loading cookies for host name: %s", qPrintable(host_name));
|
||||
foreach(const QByteArray& raw_cookie, raw_cookies) {
|
||||
QList<QByteArray> cookie_parts = raw_cookie.split('=');
|
||||
if(cookie_parts.size() == 2) {
|
||||
qDebug("Loading cookie: %s", raw_cookie.constData());
|
||||
cookies << QNetworkCookie(cookie_parts.first(), cookie_parts.last());
|
||||
}
|
||||
}
|
||||
cookie_jar->setCookiesFromUrl(cookies, url);
|
||||
m_networkManager.setCookieJar(cookie_jar);
|
||||
}
|
||||
#endif
|
||||
|
||||
void downloadThread::downloadTorrentUrl(const QString &url) {
|
||||
// Process request
|
||||
QNetworkReply *reply = downloadUrl(url, cookies);
|
||||
QNetworkReply *reply = downloadUrl(url);
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||
}
|
||||
|
||||
QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QList<QNetworkCookie>& cookies) {
|
||||
QNetworkReply* downloadThread::downloadUrl(const QString &url){
|
||||
// Update proxy settings
|
||||
applyProxySettings();
|
||||
// Set cookies
|
||||
if (!cookies.empty()) {
|
||||
qDebug("Setting %d cookies for url: %s", cookies.size(), qPrintable(url));
|
||||
m_networkManager.cookieJar()->setCookiesFromUrl(cookies, url);
|
||||
}
|
||||
#ifndef DISABLE_GUI
|
||||
// Load cookies
|
||||
QString host_name = QUrl::fromEncoded(url.toUtf8()).host();
|
||||
if(!host_name.isEmpty())
|
||||
loadCookies(host_name, url);
|
||||
#endif
|
||||
// Process download request
|
||||
qDebug("url is %s", qPrintable(url));
|
||||
const QUrl qurl = QUrl::fromEncoded(url.toUtf8());
|
||||
@@ -197,46 +147,44 @@ QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QList<QNetw
|
||||
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");
|
||||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
||||
qDebug("%d cookies for this URL", m_networkManager.cookieJar()->cookiesForUrl(url).size());
|
||||
for (int i=0; i<m_networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
|
||||
for(int i=0; i<m_networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
|
||||
qDebug("%s=%s", m_networkManager.cookieJar()->cookiesForUrl(url).at(i).name().data(), m_networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data());
|
||||
qDebug("Domain: %s, Path: %s", qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).domain()), qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).path()));
|
||||
}
|
||||
// accept gzip
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
return m_networkManager.get(request);
|
||||
}
|
||||
|
||||
void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) return;
|
||||
if (bytesTotal > 0) {
|
||||
if(!reply) return;
|
||||
if(bytesTotal > 0) {
|
||||
// Total number of bytes is available
|
||||
if (bytesTotal > 1048576*10) {
|
||||
// More than 10MB, this is probably not a torrent file, aborting...
|
||||
if(bytesTotal > 1048576) {
|
||||
// More than 1MB, this is probably not a torrent file, aborting...
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
} else {
|
||||
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||
}
|
||||
} else {
|
||||
if (bytesReceived > 1048576*10) {
|
||||
// More than 10MB, this is probably not a torrent file, aborting...
|
||||
if(bytesReceived > 1048576) {
|
||||
// More than 1MB, this is probably not a torrent file, aborting...
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadThread::applyProxySettings() {
|
||||
void downloadThread::applyProxySettings() {
|
||||
QNetworkProxy proxy;
|
||||
const Preferences pref;
|
||||
if (pref.isProxyEnabled()) {
|
||||
if(pref.isProxyEnabled()) {
|
||||
// Proxy enabled
|
||||
proxy.setHostName(pref.getProxyIp());
|
||||
proxy.setPort(pref.getProxyPort());
|
||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||
const int proxy_type = pref.getProxyType();
|
||||
if (proxy_type == Proxy::SOCKS5 || proxy_type == Proxy::SOCKS5_PW) {
|
||||
if(proxy_type == Proxy::SOCKS5 || proxy_type == Proxy::SOCKS5_PW) {
|
||||
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
} else {
|
||||
@@ -244,7 +192,7 @@ void DownloadThread::applyProxySettings() {
|
||||
proxy.setType(QNetworkProxy::HttpProxy);
|
||||
}
|
||||
// Authentication?
|
||||
if (pref.isProxyAuthEnabled()) {
|
||||
if(pref.isProxyAuthEnabled()) {
|
||||
qDebug("Proxy requires authentication, authenticating");
|
||||
proxy.setUser(pref.getProxyUsername());
|
||||
proxy.setPassword(pref.getProxyPassword());
|
||||
@@ -255,8 +203,8 @@ void DownloadThread::applyProxySettings() {
|
||||
m_networkManager.setProxy(proxy);
|
||||
}
|
||||
|
||||
QString DownloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
switch(status) {
|
||||
QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
switch(status){
|
||||
case QNetworkReply::HostNotFoundError:
|
||||
return tr("The remote host name was not found (invalid hostname)");
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
@@ -305,7 +253,7 @@ QString DownloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void DownloadThread::ignoreSslErrors(QNetworkReply* reply, const QList<QSslError> &errors) {
|
||||
void downloadThread::ignoreSslErrors(QNetworkReply* reply, const QList<QSslError> &errors) {
|
||||
Q_UNUSED(errors)
|
||||
// Ignore all SSL errors
|
||||
reply->ignoreSslErrors();
|
||||
|
||||
@@ -32,29 +32,24 @@
|
||||
#define DOWNLOADTHREAD_H
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkCookie>
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QSslError>
|
||||
#include <zlib.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QNetworkAccessManager;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class DownloadThread : public QObject {
|
||||
class downloadThread : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DownloadThread(QObject* parent = 0);
|
||||
QNetworkReply* downloadUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
void downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
downloadThread(QObject* parent = 0);
|
||||
QNetworkReply* downloadUrl(const QString &url);
|
||||
void downloadTorrentUrl(const QString &url);
|
||||
//void setProxy(QString IP, int port, QString username, QString password);
|
||||
|
||||
signals:
|
||||
void downloadFinished(const QString &url, const QString &file_path);
|
||||
void downloadFailure(const QString &url, const QString &reason);
|
||||
void magnetRedirect(const QString &url_new, const QString &url_old);
|
||||
|
||||
private slots:
|
||||
void processDlFinished(QNetworkReply* reply);
|
||||
@@ -64,9 +59,11 @@ private slots:
|
||||
#endif
|
||||
|
||||
private:
|
||||
static QByteArray gUncompress(Bytef *inData, size_t len);
|
||||
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
void applyProxySettings();
|
||||
#ifndef DISABLE_GUI
|
||||
void loadCookies(const QString &host_name, QString url);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QNetworkAccessManager m_networkManager;
|
||||
|
||||
@@ -1,79 +1,32 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QListWidgetItem>
|
||||
#include <QLabel>
|
||||
#include "executionlog.h"
|
||||
#include "ui_executionlog.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "loglistwidget.h"
|
||||
|
||||
ExecutionLog::ExecutionLog(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExecutionLog),
|
||||
m_logList(new LogListWidget(MAX_LOG_MESSAGES)),
|
||||
m_banList(new LogListWidget(MAX_LOG_MESSAGES))
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExecutionLog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->tabConsole->setTabIcon(0, IconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
ui->tabConsole->setTabIcon(1, IconProvider::instance()->getIcon("view-filter"));
|
||||
ui->tabGeneral->layout()->addWidget(m_logList);
|
||||
ui->tabBan->layout()->addWidget(m_banList);
|
||||
|
||||
const QStringList log_msgs = QBtSession::instance()->getConsoleMessages();
|
||||
foreach (const QString& msg, log_msgs)
|
||||
addLogMessage(msg);
|
||||
const QStringList ban_msgs = QBtSession::instance()->getPeerBanMessages();
|
||||
foreach (const QString& msg, ban_msgs)
|
||||
addBanMessage(msg);
|
||||
ui->textConsole->setHtml(QBtSession::instance()->getConsoleMessages().join("<br>"));
|
||||
connect(QBtSession::instance(), SIGNAL(newConsoleMessage(QString)), SLOT(addLogMessage(QString)));
|
||||
ui->textBannedPeers->setHtml(QBtSession::instance()->getPeerBanMessages().join("<br>"));
|
||||
connect(QBtSession::instance(), SIGNAL(newBanMessage(QString)), SLOT(addBanMessage(QString)));
|
||||
connect(m_logList, SIGNAL(logCleared()), QBtSession::instance(), SLOT(clearConsoleMessages()));
|
||||
connect(m_banList, SIGNAL(logCleared()), QBtSession::instance(), SLOT(clearPeerBanMessages()));
|
||||
}
|
||||
|
||||
ExecutionLog::~ExecutionLog()
|
||||
{
|
||||
delete m_logList;
|
||||
delete m_banList;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ExecutionLog::addLogMessage(const QString &msg)
|
||||
{
|
||||
m_logList->appendLine(msg);
|
||||
ui->textConsole->setHtml(msg+ui->textConsole->toHtml());
|
||||
}
|
||||
|
||||
void ExecutionLog::addBanMessage(const QString &msg)
|
||||
{
|
||||
m_banList->appendLine(msg);
|
||||
ui->textBannedPeers->setHtml(msg+ui->textBannedPeers->toHtml());
|
||||
}
|
||||
|
||||
@@ -1,44 +1,11 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef EXECUTIONLOG_H
|
||||
#define EXECUTIONLOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class ExecutionLog;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
class LogListWidget;
|
||||
|
||||
class ExecutionLog : public QWidget
|
||||
{
|
||||
@@ -53,10 +20,7 @@ public slots:
|
||||
void addBanMessage(const QString &msg);
|
||||
|
||||
private:
|
||||
Ui::ExecutionLog *ui;
|
||||
|
||||
LogListWidget *m_logList;
|
||||
LogListWidget *m_banList;
|
||||
Ui::ExecutionLog *ui;
|
||||
};
|
||||
|
||||
#endif // EXECUTIONLOG_H
|
||||
|
||||
@@ -22,17 +22,25 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout"/>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textConsole"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabBan">
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Blocked IPs</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="_2"/>
|
||||
<layout class="QVBoxLayout" name="_2">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBannedPeers"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifndef CIFS_MAGIC_NUMBER
|
||||
@@ -60,11 +59,11 @@ private:
|
||||
private:
|
||||
static bool isNetworkFileSystem(QString path) {
|
||||
QString file = path;
|
||||
if (!file.endsWith(QDir::separator()))
|
||||
if(!file.endsWith(QDir::separator()))
|
||||
file += QDir::separator();
|
||||
file += ".";
|
||||
struct statfs buf;
|
||||
if (!statfs(file.toLocal8Bit().constData(), &buf)) {
|
||||
if(!statfs(file.toLocal8Bit().constData(), &buf)) {
|
||||
#ifdef Q_WS_MAC
|
||||
// XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined?
|
||||
return (strcmp(buf.f_fstypename, "nfs") == 0 || strcmp(buf.f_fstypename, "cifs") == 0 || strcmp(buf.f_fstypename, "smbfs") == 0);
|
||||
@@ -119,23 +118,23 @@ private:
|
||||
|
||||
public:
|
||||
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
||||
m_filters << "*.torrent" << "*.magnet";
|
||||
m_filters << "*.torrent";
|
||||
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
||||
}
|
||||
|
||||
~FileSystemWatcher() {
|
||||
#ifndef Q_WS_WIN
|
||||
if (watch_timer)
|
||||
if(watch_timer)
|
||||
delete watch_timer;
|
||||
#endif
|
||||
if (m_partialTorrentTimer)
|
||||
if(m_partialTorrentTimer)
|
||||
delete m_partialTorrentTimer;
|
||||
}
|
||||
|
||||
QStringList directories() const {
|
||||
QStringList dirs;
|
||||
#ifndef Q_WS_WIN
|
||||
if (watch_timer) {
|
||||
if(watch_timer) {
|
||||
foreach (const QDir &dir, watched_folders)
|
||||
dirs << dir.canonicalPath();
|
||||
}
|
||||
@@ -150,7 +149,7 @@ public:
|
||||
if (!dir.exists())
|
||||
return;
|
||||
// Check if the path points to a network file system or not
|
||||
if (isNetworkFileSystem(path)) {
|
||||
if(isNetworkFileSystem(path)) {
|
||||
// Network mode
|
||||
qDebug("Network folder detected: %s", qPrintable(path));
|
||||
qDebug("Using file polling mode instead of inotify...");
|
||||
@@ -195,7 +194,7 @@ protected slots:
|
||||
// Local folders scan
|
||||
addTorrentsFromDir(QDir(path), torrents);
|
||||
// Report detected torrent files
|
||||
if (!torrents.empty()) {
|
||||
if(!torrents.empty()) {
|
||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||
emit torrentsAdded(torrents);
|
||||
}
|
||||
@@ -211,7 +210,7 @@ protected slots:
|
||||
addTorrentsFromDir(dir, torrents);
|
||||
}
|
||||
// Report detected torrent files
|
||||
if (!torrents.empty()) {
|
||||
if(!torrents.empty()) {
|
||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||
emit torrentsAdded(torrents);
|
||||
}
|
||||
@@ -222,16 +221,16 @@ protected slots:
|
||||
QStringList no_longer_partial;
|
||||
|
||||
// Check which torrents are still partial
|
||||
foreach (const QString& torrent_path, m_partialTorrents.keys()) {
|
||||
if (!QFile::exists(torrent_path)) {
|
||||
foreach(const QString& torrent_path, m_partialTorrents.keys()) {
|
||||
if(!QFile::exists(torrent_path)) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
continue;
|
||||
}
|
||||
if (fsutils::isValidTorrentFile(torrent_path)) {
|
||||
if(misc::isValidTorrentFile(torrent_path)) {
|
||||
no_longer_partial << torrent_path;
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
} else {
|
||||
if (m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||
if(m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
QFile::rename(torrent_path, torrent_path+".invalid");
|
||||
} else {
|
||||
@@ -241,7 +240,7 @@ protected slots:
|
||||
}
|
||||
|
||||
// Stop the partial timer if necessary
|
||||
if (m_partialTorrents.empty()) {
|
||||
if(m_partialTorrents.empty()) {
|
||||
m_partialTorrentTimer->stop();
|
||||
m_partialTorrentTimer->deleteLater();
|
||||
qDebug("No longer any partial torrent.");
|
||||
@@ -250,7 +249,7 @@ protected slots:
|
||||
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
||||
}
|
||||
// Notify of new torrents
|
||||
if (!no_longer_partial.isEmpty())
|
||||
if(!no_longer_partial.isEmpty())
|
||||
emit torrentsAdded(no_longer_partial);
|
||||
}
|
||||
|
||||
@@ -260,7 +259,7 @@ signals:
|
||||
private:
|
||||
void startPartialTorrentTimer() {
|
||||
Q_ASSERT(!m_partialTorrents.isEmpty());
|
||||
if (!m_partialTorrentTimer) {
|
||||
if(!m_partialTorrentTimer) {
|
||||
m_partialTorrentTimer = new QTimer();
|
||||
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
|
||||
m_partialTorrentTimer->setSingleShot(true);
|
||||
@@ -270,25 +269,19 @@ private:
|
||||
|
||||
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
|
||||
const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted);
|
||||
foreach (const QString &file, files) {
|
||||
foreach(const QString &file, files) {
|
||||
const QString file_abspath = dir.absoluteFilePath(file);
|
||||
if (file_abspath.endsWith(".magnet")) {
|
||||
QFile f(file_abspath);
|
||||
if (f.open(QIODevice::ReadOnly)
|
||||
&& !misc::magnetUriToHash(QString::fromLocal8Bit(f.readAll())).isEmpty()) {
|
||||
torrents << file_abspath;
|
||||
}
|
||||
} else if (fsutils::isValidTorrentFile(file_abspath)) {
|
||||
if(misc::isValidTorrentFile(file_abspath)) {
|
||||
torrents << file_abspath;
|
||||
} else {
|
||||
if (!m_partialTorrents.contains(file_abspath)) {
|
||||
if(!m_partialTorrents.contains(file_abspath)) {
|
||||
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
|
||||
qDebug("Delay the file's processing...");
|
||||
m_partialTorrents.insert(file_abspath, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_partialTorrents.empty())
|
||||
if(!m_partialTorrents.empty())
|
||||
startPartialTorrentTimer();
|
||||
}
|
||||
|
||||
|
||||
503
src/fs_utils.cpp
@@ -1,503 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#ifdef DISABLE_GUI
|
||||
#include <QCoreApplication>
|
||||
#else
|
||||
#include <QApplication>
|
||||
#endif
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
#if defined(Q_WS_MAC) || defined(Q_OS_FREEBSD)
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#else
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#else
|
||||
#include <shlobj.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
#include <QDesktopServices>
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
/**
|
||||
* Converts a path to a string suitable for display.
|
||||
* This function makes sure the directory separator used is consistent
|
||||
* with the OS being run.
|
||||
*/
|
||||
QString fsutils::toDisplayPath(const QString& path)
|
||||
{
|
||||
return QDir::toNativeSeparators(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file extension part of a file name.
|
||||
*/
|
||||
QString fsutils::fileExtension(const QString &filename)
|
||||
{
|
||||
const int point_index = filename.lastIndexOf(".");
|
||||
return (point_index >= 0) ? filename.mid(point_index + 1) : QString();
|
||||
}
|
||||
|
||||
QString fsutils::fileName(const QString& file_path)
|
||||
{
|
||||
const int slash_index = file_path.lastIndexOf(QRegExp("[/\\\\]"));
|
||||
if (slash_index == -1)
|
||||
return file_path;
|
||||
return file_path.mid(slash_index + 1);
|
||||
}
|
||||
|
||||
bool fsutils::isValidTorrentFile(const QString& torrent_path) {
|
||||
try {
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t = new torrent_info(torrent_path.toUtf8().constData());
|
||||
if (!t->is_valid() || t->num_files() == 0)
|
||||
return false;
|
||||
} catch(std::exception&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty folder tree.
|
||||
*
|
||||
* This function will also remove .DS_Store files on Mac OS and
|
||||
* Thumbs.db on Windows.
|
||||
*/
|
||||
bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << dir_path;
|
||||
if (dir_path.isEmpty())
|
||||
return false;
|
||||
|
||||
QDir dir(dir_path);
|
||||
if (!dir.exists())
|
||||
return true;
|
||||
|
||||
// Remove Files created by the OS
|
||||
#if defined Q_WS_MAC
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/.DS_Store"));
|
||||
#elif defined Q_WS_WIN
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/Thumbs.db"));
|
||||
#endif
|
||||
|
||||
QFileInfoList sub_files = dir.entryInfoList();
|
||||
foreach (const QFileInfo& info, sub_files) {
|
||||
QString sub_name = info.fileName();
|
||||
if (sub_name == "." || sub_name == "..")
|
||||
continue;
|
||||
|
||||
QString sub_path = info.absoluteFilePath();
|
||||
qDebug() << Q_FUNC_INFO << "sub file: " << sub_path;
|
||||
if (info.isDir()) {
|
||||
if (!smartRemoveEmptyFolderTree(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove folder: " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (info.isHidden()) {
|
||||
qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path;
|
||||
if (!fsutils::forceRemove(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Folder is not empty, aborting. Found: " << sub_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "Calling rmdir on " << dir_path;
|
||||
return QDir().rmdir(dir_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the file with the given file_path.
|
||||
*
|
||||
* This function will try to fix the file permissions before removing it.
|
||||
*/
|
||||
bool fsutils::forceRemove(const QString& file_path)
|
||||
{
|
||||
QFile f(file_path);
|
||||
if (!f.exists())
|
||||
return true;
|
||||
// Make sure we have read/write permissions
|
||||
f.setPermissions(f.permissions()|QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
|
||||
// Remove the file
|
||||
return f.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a file.
|
||||
* If the file is a folder, it will compute its size based on its content.
|
||||
*
|
||||
* Returns -1 in case of error.
|
||||
*/
|
||||
qint64 fsutils::computePathSize(const QString& path)
|
||||
{
|
||||
// Check if it is a file
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists()) return -1;
|
||||
if (fi.isFile()) return fi.size();
|
||||
// Compute folder size based on its content
|
||||
qint64 size = 0;
|
||||
foreach (const QFileInfo &subfi, QDir(path).entryInfoList(QDir::Dirs|QDir::Files)) {
|
||||
if (subfi.fileName().startsWith(".")) continue;
|
||||
if (subfi.isDir())
|
||||
size += fsutils::computePathSize(subfi.absoluteFilePath());
|
||||
else
|
||||
size += subfi.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes deep comparison of two files to make sure they are identical.
|
||||
*/
|
||||
bool fsutils::sameFiles(const QString& path1, const QString& path2)
|
||||
{
|
||||
QFile f1(path1), f2(path2);
|
||||
if (!f1.exists() || !f2.exists()) return false;
|
||||
if (f1.size() != f2.size()) return false;
|
||||
if (!f1.open(QIODevice::ReadOnly)) return false;
|
||||
if (!f2.open(QIODevice::ReadOnly)) {
|
||||
f1.close();
|
||||
return false;
|
||||
}
|
||||
bool same = true;
|
||||
while(!f1.atEnd() && !f2.atEnd()) {
|
||||
if (f1.read(1024) != f2.read(1024)) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f1.close(); f2.close();
|
||||
return same;
|
||||
}
|
||||
|
||||
QString fsutils::updateLabelInSavePath(QString defaultSavePath,QString save_path, const QString& old_label, const QString& new_label) {
|
||||
if (old_label == new_label) return save_path;
|
||||
defaultSavePath.replace("\\", "/");
|
||||
save_path.replace("\\", "/");
|
||||
qDebug("UpdateLabelInSavePath(%s, %s, %s)", qPrintable(save_path), qPrintable(old_label), qPrintable(new_label));
|
||||
if (!save_path.startsWith(defaultSavePath)) return save_path;
|
||||
QString new_save_path = save_path;
|
||||
new_save_path.replace(defaultSavePath, "");
|
||||
QStringList path_parts = new_save_path.split("/", QString::SkipEmptyParts);
|
||||
if (path_parts.empty()) {
|
||||
if (!new_label.isEmpty())
|
||||
path_parts << new_label;
|
||||
} else {
|
||||
if (old_label.isEmpty() || path_parts.first() != old_label) {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.prepend(new_label);
|
||||
} else {
|
||||
if (new_label.isEmpty()) {
|
||||
path_parts.removeAt(0);
|
||||
} else {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.replace(0, new_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
new_save_path = defaultSavePath;
|
||||
if (!new_save_path.endsWith(QDir::separator())) new_save_path += QDir::separator();
|
||||
new_save_path += path_parts.join(QDir::separator());
|
||||
qDebug("New save path is %s", qPrintable(new_save_path));
|
||||
return new_save_path;
|
||||
}
|
||||
|
||||
QString fsutils::toValidFileSystemName(QString filename) {
|
||||
qDebug("toValidFSName: %s", qPrintable(filename));
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
filename.replace(regex, " ");
|
||||
qDebug("toValidFSName, result: %s", qPrintable(filename));
|
||||
return filename.trimmed();
|
||||
}
|
||||
|
||||
bool fsutils::isValidFileSystemName(const QString& filename) {
|
||||
if (filename.isEmpty()) return false;
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
return !filename.contains(regex);
|
||||
}
|
||||
|
||||
long long fsutils::freeDiskSpaceOnPath(QString path) {
|
||||
if (path.isEmpty()) return -1;
|
||||
path.replace("\\", "/");
|
||||
QDir dir_path(path);
|
||||
if (!dir_path.exists()) {
|
||||
QStringList parts = path.split("/");
|
||||
while (parts.size() > 1 && !QDir(parts.join("/")).exists()) {
|
||||
parts.removeLast();
|
||||
}
|
||||
dir_path = QDir(parts.join("/"));
|
||||
if (!dir_path.exists()) return -1;
|
||||
}
|
||||
Q_ASSERT(dir_path.exists());
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
unsigned long long available;
|
||||
struct statfs stats;
|
||||
const QString statfs_path = dir_path.path()+"/.";
|
||||
const int ret = statfs (qPrintable(statfs_path), &stats) ;
|
||||
if (ret == 0) {
|
||||
available = ((unsigned long long)stats.f_bavail) *
|
||||
((unsigned long long)stats.f_bsize) ;
|
||||
return available;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER);
|
||||
GetDiskFreeSpaceEx_t
|
||||
pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
|
||||
(
|
||||
::GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetDiskFreeSpaceExW"
|
||||
);
|
||||
if ( pGetDiskFreeSpaceEx )
|
||||
{
|
||||
ULARGE_INTEGER bytesFree, bytesTotal;
|
||||
unsigned long long *ret;
|
||||
if (pGetDiskFreeSpaceEx((LPCTSTR)(QDir::toNativeSeparators(dir_path.path())).utf16(), &bytesFree, &bytesTotal, NULL)) {
|
||||
ret = (unsigned long long*)&bytesFree;
|
||||
return *ret;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::branchPath(const QString& file_path, QString* removed)
|
||||
{
|
||||
QString ret = file_path;
|
||||
if (ret.endsWith("/") || ret.endsWith("\\"))
|
||||
ret.chop(1);
|
||||
const int slashIndex = ret.lastIndexOf(QRegExp("[/\\\\]"));
|
||||
if (slashIndex >= 0) {
|
||||
if (removed)
|
||||
*removed = ret.mid(slashIndex + 1);
|
||||
ret = ret.left(slashIndex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool fsutils::sameFileNames(const QString &first, const QString &second)
|
||||
{
|
||||
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
|
||||
return QString::compare(first, second, Qt::CaseSensitive) == 0;
|
||||
#else
|
||||
return QString::compare(first, second, Qt::CaseInsensitive) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Replace ~ in path
|
||||
QString fsutils::expandPath(const QString& path) {
|
||||
QString ret = path.trimmed();
|
||||
if (ret.isEmpty()) return ret;
|
||||
if (ret == "~")
|
||||
return QDir::homePath();
|
||||
if (ret[0] == '~' && (ret[1] == '/' || ret[1] == '\\')) {
|
||||
ret.replace(0, 1, QDir::homePath());
|
||||
} else {
|
||||
if (!QDir::isAbsolutePath(ret))
|
||||
ret = QDir(ret).absolutePath();
|
||||
}
|
||||
return QDir::cleanPath(path);
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDataLocation() {
|
||||
#ifdef Q_WS_WIN
|
||||
LPWSTR path=new WCHAR[256];
|
||||
QString result;
|
||||
#if defined Q_WS_WINCE
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE))
|
||||
#else
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||
#endif
|
||||
result = QString::fromWCharArray(path);
|
||||
if (!QCoreApplication::applicationName().isEmpty())
|
||||
result = result + QLatin1String("\\") + qApp->applicationName();
|
||||
if (!result.endsWith("\\"))
|
||||
result += "\\";
|
||||
return result;
|
||||
#else
|
||||
#ifdef Q_WS_MAC
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
path = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
path += QLatin1Char('/') + qApp->applicationName();
|
||||
return path;
|
||||
#else
|
||||
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
||||
if (xdgDataHome.isEmpty())
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||
xdgDataHome += QLatin1String("/data/")
|
||||
+ qApp->applicationName();
|
||||
return xdgDataHome;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesCacheLocation() {
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
return QDesktopServicesDataLocation() + QLatin1String("\\cache");
|
||||
#else
|
||||
#ifdef Q_WS_MAC
|
||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
path = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
path += QLatin1Char('/') + qApp->applicationName();
|
||||
return path;
|
||||
#else
|
||||
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
||||
if (xdgCacheHome.isEmpty())
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
|
||||
return xdgCacheHome;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDownloadLocation() {
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
// as long as it stays WinXP like we do the same on OS/2
|
||||
// TODO: Use IKnownFolderManager to get path of FOLDERID_Downloads
|
||||
// instead of hardcoding "Downloads"
|
||||
// Unfortunately, this would break compatibility with WinXP
|
||||
return QDir(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).absoluteFilePath(tr("Downloads"));
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
QString save_path;
|
||||
// Default save path on Linux
|
||||
QString config_path = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME").constData());
|
||||
if (config_path.isEmpty())
|
||||
config_path = QDir::home().absoluteFilePath(".config");
|
||||
|
||||
QString user_dirs_file = config_path + "/user-dirs.dirs";
|
||||
if (QFile::exists(user_dirs_file)) {
|
||||
QSettings settings(user_dirs_file, QSettings::IniFormat);
|
||||
// We need to force UTF-8 encoding here since this is not
|
||||
// the default for Ini files.
|
||||
settings.setIniCodec("UTF-8");
|
||||
QString xdg_download_dir = settings.value("XDG_DOWNLOAD_DIR").toString();
|
||||
if (!xdg_download_dir.isEmpty()) {
|
||||
// Resolve $HOME environment variables
|
||||
xdg_download_dir.replace("$HOME", QDir::homePath());
|
||||
save_path = xdg_download_dir;
|
||||
qDebug() << Q_FUNC_INFO << "SUCCESS: Using XDG path for downloads: " << save_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if (!save_path.isEmpty() && !QFile::exists(save_path)) {
|
||||
QDir().mkpath(save_path);
|
||||
}
|
||||
|
||||
if (save_path.isEmpty() || !QFile::exists(save_path)) {
|
||||
save_path = QDir::home().absoluteFilePath(tr("Downloads"));
|
||||
qDebug() << Q_FUNC_INFO << "using" << save_path << "as fallback since the XDG detection did not work";
|
||||
}
|
||||
|
||||
return save_path;
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
// TODO: How to support this on Mac OS X?
|
||||
#endif
|
||||
|
||||
// Fallback
|
||||
return QDir::home().absoluteFilePath(tr("Downloads"));
|
||||
}
|
||||
|
||||
QString fsutils::searchEngineLocation() {
|
||||
QString folder = "nova";
|
||||
if (misc::pythonVersion() >= 3)
|
||||
folder = "nova3";
|
||||
const QString location = QDir::cleanPath(QDesktopServicesDataLocation()
|
||||
+ QDir::separator() + folder);
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::BTBackupLocation() {
|
||||
const QString location = QDir::cleanPath(QDesktopServicesDataLocation()
|
||||
+ QDir::separator() + "BT_backup");
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::cacheLocation() {
|
||||
QString location = QDir::cleanPath(QDesktopServicesCacheLocation());
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FS_UTILS_H
|
||||
#define FS_UTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QCoreApplication>
|
||||
|
||||
/**
|
||||
* Utility functions related to file system.
|
||||
*/
|
||||
class fsutils
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(fsutils)
|
||||
|
||||
public:
|
||||
static QString toDisplayPath(const QString& path);
|
||||
static QString fileExtension(const QString& filename);
|
||||
static QString fileName(const QString& file_path);
|
||||
static qint64 computePathSize(const QString& path);
|
||||
static bool sameFiles(const QString& path1, const QString& path2);
|
||||
static QString updateLabelInSavePath(QString defaultSavePath, QString save_path, const QString& old_label, const QString& new_label);
|
||||
static QString toValidFileSystemName(QString filename);
|
||||
static bool isValidFileSystemName(const QString& filename);
|
||||
static long long freeDiskSpaceOnPath(QString path);
|
||||
static QString branchPath(const QString& file_path, QString* removed = 0);
|
||||
static bool sameFileNames(const QString& first, const QString& second);
|
||||
static QString expandPath(const QString& path);
|
||||
static bool isValidTorrentFile(const QString& path);
|
||||
static bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
||||
static bool forceRemove(const QString& file_path);
|
||||
|
||||
/* Ported from Qt4 to drop dependency on QtGui */
|
||||
static QString QDesktopServicesDataLocation();
|
||||
static QString QDesktopServicesCacheLocation();
|
||||
static QString QDesktopServicesDownloadLocation();
|
||||
/* End of Qt4 code */
|
||||
static QString searchEngineLocation();
|
||||
static QString BTBackupLocation();
|
||||
static QString cacheLocation();
|
||||
|
||||
};
|
||||
|
||||
#endif // FS_UTILS_H
|
||||
|
||||
@@ -64,20 +64,20 @@
|
||||
#include <QFile>
|
||||
#include <QChar>
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
QString GeoIPManager::geoipFolder(bool embedded) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
if (embedded)
|
||||
if(embedded)
|
||||
return ":/geoip/";
|
||||
return fsutils::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
||||
return misc::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
||||
#else
|
||||
Q_UNUSED(embedded);
|
||||
if (QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||
if(QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||
return "/usr/local/share/GeoIP/";
|
||||
if (QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
|
||||
if(QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
|
||||
return "/var/lib/GeoIP/";
|
||||
return "/usr/share/GeoIP/";
|
||||
#endif
|
||||
@@ -89,22 +89,22 @@ QString GeoIPManager::geoipDBpath(bool embedded) {
|
||||
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
void GeoIPManager::exportEmbeddedDb() {
|
||||
if (!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
|
||||
if(!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
|
||||
qDebug("A local Geoip database update is required, proceeding...");
|
||||
// Create geoip folder is necessary
|
||||
QDir gfolder(geoipFolder(false));
|
||||
if (!gfolder.exists()) {
|
||||
if (!gfolder.mkpath(geoipFolder(false))) {
|
||||
if(!gfolder.exists()) {
|
||||
if(!gfolder.mkpath(geoipFolder(false))) {
|
||||
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Remove destination files
|
||||
if (QFile::exists(geoipDBpath(false)))
|
||||
fsutils::forceRemove(geoipDBpath(false));
|
||||
if(QFile::exists(geoipDBpath(false)))
|
||||
misc::safeRemove(geoipDBpath(false));
|
||||
// Copy from executable to hard disk
|
||||
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
|
||||
if (!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
if(!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
|
||||
}
|
||||
qDebug("Local Geoip database was updated");
|
||||
@@ -116,7 +116,7 @@ void GeoIPManager::loadDatabase(session *s) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
exportEmbeddedDb();
|
||||
#endif
|
||||
if (QFile::exists(geoipDBpath(false))) {
|
||||
if(QFile::exists(geoipDBpath(false))) {
|
||||
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
||||
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
|
||||
} else {
|
||||
@@ -183,9 +183,9 @@ const char * country_name[253] =
|
||||
"Saint Barthelemy","Saint Martin"};
|
||||
|
||||
QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||
if (iso[0] == 0) return "N/A";
|
||||
for (uint i = 0; i < num_countries; ++i) {
|
||||
if (iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||
if(iso[0] == 0) return "N/A";
|
||||
for(uint i = 0; i < num_countries; ++i) {
|
||||
if(iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||
return QLatin1String(country_name[i]);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
QIcon GeoIPManager::CountryISOCodeToIcon(const char* iso) {
|
||||
if (iso[0] == 0 || iso[0] == '!') return QIcon();
|
||||
if(iso[0] == 0 || iso[0] == '!') return QIcon();
|
||||
const QString isoStr = QString(QByteArray(iso, 2)).toLower();
|
||||
return QIcon(":/Icons/flags/"+isoStr+".png");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ class HeadlessLoader: public QObject {
|
||||
|
||||
public:
|
||||
HeadlessLoader(const QStringList &torrentCmdLine) {
|
||||
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(shutdownCleanUp()), Qt::DirectConnection);
|
||||
Preferences pref;
|
||||
// Enable Web UI
|
||||
pref.setWebUiEnabled(true);
|
||||
@@ -56,18 +55,17 @@ public:
|
||||
std::cout << qPrintable(tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(pref.getWebUiPort()))) << std::endl;
|
||||
std::cout << qPrintable(tr("The Web UI administrator user name is: %1").arg(pref.getWebUiUsername())) << std::endl;
|
||||
qDebug() << "Password:" << pref.getWebUiPassword();
|
||||
if (pref.getWebUiPassword() == "32fe0bd2bb001911bb8bcfe23fc92b63") {
|
||||
if(pref.getWebUiPassword() == "32fe0bd2bb001911bb8bcfe23fc92b63") {
|
||||
std::cout << qPrintable(tr("The Web UI administrator password is still the default one: %1").arg("adminadmin")) << std::endl;
|
||||
std::cout << qPrintable(tr("This is a security risk, please consider changing your password from program preferences.")) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void shutdownCleanUp() {
|
||||
Preferences().sync();
|
||||
~HeadlessLoader() {
|
||||
QBtSession::drop();
|
||||
}
|
||||
|
||||
public slots:
|
||||
// Call this function to exit qBittorrent headless loader
|
||||
// and return to prompt (object will be deleted by main)
|
||||
void exit() {
|
||||
@@ -87,16 +85,16 @@ public slots:
|
||||
// the right addTorrent function, considering
|
||||
// the parameter type.
|
||||
void processParams(const QStringList& params) {
|
||||
foreach (QString param, params) {
|
||||
foreach(QString param, params) {
|
||||
param = param.trimmed();
|
||||
if (param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->downloadFromUrl(param);
|
||||
}else{
|
||||
if (param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
param = misc::bcLinkToMagnet(param);
|
||||
}
|
||||
if (param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->addMagnetUri(param);
|
||||
} else {
|
||||
QBtSession::instance()->addTorrent(param);
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
protected:
|
||||
void tabInserted(int index) {
|
||||
QTabWidget::tabInserted(index);
|
||||
if (count() == 1) {
|
||||
if(count() == 1) {
|
||||
showTabBar(false);
|
||||
} else {
|
||||
showTabBar(true);
|
||||
@@ -53,7 +53,7 @@ protected:
|
||||
|
||||
void tabRemoved(int index) {
|
||||
QTabWidget::tabInserted(index);
|
||||
if (count() == 1) {
|
||||
if(count() == 1) {
|
||||
showTabBar(false);
|
||||
} else {
|
||||
showTabBar(true);
|
||||
|
||||
@@ -35,21 +35,21 @@ IconProvider* IconProvider::m_instance = 0;
|
||||
|
||||
IconProvider::IconProvider()
|
||||
{
|
||||
#if defined(Q_WS_X11)
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
m_useSystemTheme = Preferences().useSystemIconTheme();
|
||||
#endif
|
||||
}
|
||||
|
||||
IconProvider * IconProvider::instance()
|
||||
{
|
||||
if (!m_instance)
|
||||
if(!m_instance)
|
||||
m_instance = new IconProvider;
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void IconProvider::drop()
|
||||
{
|
||||
if (m_instance) {
|
||||
if(m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
@@ -57,8 +57,8 @@ void IconProvider::drop()
|
||||
|
||||
QIcon IconProvider::getIcon(const QString &iconId)
|
||||
{
|
||||
#if defined(Q_WS_X11)
|
||||
if (m_useSystemTheme) {
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
if(m_useSystemTheme) {
|
||||
QIcon icon = QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
|
||||
icon = generateDifferentSizes(icon);
|
||||
return icon;
|
||||
@@ -67,31 +67,27 @@ QIcon IconProvider::getIcon(const QString &iconId)
|
||||
return QIcon(":/Icons/oxygen/"+iconId+".png");
|
||||
}
|
||||
|
||||
#if defined(Q_WS_X11)
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
void IconProvider::useSystemIconTheme(bool enable)
|
||||
{
|
||||
m_useSystemTheme = enable;
|
||||
}
|
||||
|
||||
// Makes sure the icon is at least available in 16px and 24px size
|
||||
// It scales the icon from the theme if necessary
|
||||
// Otherwise, the UI looks broken if the icon is not available
|
||||
// in the correct size.
|
||||
QIcon IconProvider::generateDifferentSizes(const QIcon& icon)
|
||||
QIcon IconProvider::generateDifferentSizes(const QIcon &icon)
|
||||
{
|
||||
QIcon new_icon;
|
||||
QList<QSize> required_sizes;
|
||||
required_sizes << QSize(16, 16) << QSize(24, 24);
|
||||
QList<QIcon::Mode> modes;
|
||||
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
|
||||
foreach (const QSize& size, required_sizes) {
|
||||
foreach (QIcon::Mode mode, modes) {
|
||||
foreach(const QSize& size, required_sizes) {
|
||||
foreach(QIcon::Mode mode, modes) {
|
||||
QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off);
|
||||
if (pixoff.height() > size.height())
|
||||
if(pixoff.height() > size.height())
|
||||
pixoff = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
new_icon.addPixmap(pixoff, mode, QIcon::Off);
|
||||
QPixmap pixon = icon.pixmap(size, mode, QIcon::On);
|
||||
if (pixon.height() > size.height())
|
||||
if(pixon.height() > size.height())
|
||||
pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
new_icon.addPixmap(pixon, mode, QIcon::On);
|
||||
}
|
||||
@@ -100,14 +96,14 @@ QIcon IconProvider::generateDifferentSizes(const QIcon& icon)
|
||||
}
|
||||
#endif
|
||||
|
||||
QString IconProvider::getIconPath(const QString& iconId)
|
||||
QString IconProvider::getIconPath(const QString &iconId)
|
||||
{
|
||||
#if defined(Q_WS_X11)
|
||||
if (m_useSystemTheme) {
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
if(m_useSystemTheme) {
|
||||
QString path = QDir::temp().absoluteFilePath(iconId+".png");
|
||||
if (!QFile::exists(path)) {
|
||||
if(!QFile::exists(path)) {
|
||||
const QIcon icon = QIcon::fromTheme(iconId);
|
||||
if (icon.isNull()) return ":/Icons/oxygen/"+iconId+".png";
|
||||
if(icon.isNull()) return ":/Icons/oxygen/"+iconId+".png";
|
||||
QPixmap px = icon.pixmap(32);
|
||||
px.save(path);
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ public:
|
||||
static IconProvider* instance();
|
||||
static void drop();
|
||||
QIcon getIcon(const QString& iconId);
|
||||
QString getIconPath(const QString& iconId);
|
||||
QString getIconPath(const QString &iconId);
|
||||
|
||||
#if defined(Q_WS_X11)
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
public:
|
||||
void useSystemIconTheme(bool enable);
|
||||
|
||||
|
||||
673
src/icons.qrc
@@ -1,353 +1,348 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>Icons/3-state-checkbox.gif</file>
|
||||
<file>Icons/L.gif</file>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/3-state-checkbox.gif</file>
|
||||
<file>Icons/uparrow.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/downarrow.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/magnet.png</file>
|
||||
<file>Icons/slow.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/flags/ad.png</file>
|
||||
<file>Icons/flags/ae.png</file>
|
||||
<file>Icons/flags/af.png</file>
|
||||
<file>Icons/flags/ag.png</file>
|
||||
<file>Icons/flags/ai.png</file>
|
||||
<file>Icons/flags/al.png</file>
|
||||
<file>Icons/flags/am.png</file>
|
||||
<file>Icons/flags/an.png</file>
|
||||
<file>Icons/flags/ao.png</file>
|
||||
<file>Icons/flags/ar.png</file>
|
||||
<file>Icons/flags/as.png</file>
|
||||
<file>Icons/flags/at.png</file>
|
||||
<file>Icons/flags/au.png</file>
|
||||
<file>Icons/flags/aw.png</file>
|
||||
<file>Icons/flags/ax.png</file>
|
||||
<file>Icons/flags/az.png</file>
|
||||
<file>Icons/flags/ba.png</file>
|
||||
<file>Icons/flags/bb.png</file>
|
||||
<file>Icons/flags/bd.png</file>
|
||||
<file>Icons/flags/be.png</file>
|
||||
<file>Icons/flags/bf.png</file>
|
||||
<file>Icons/flags/bg.png</file>
|
||||
<file>Icons/flags/bh.png</file>
|
||||
<file>Icons/flags/bi.png</file>
|
||||
<file>Icons/flags/bj.png</file>
|
||||
<file>Icons/flags/bm.png</file>
|
||||
<file>Icons/flags/bn.png</file>
|
||||
<file>Icons/flags/bo.png</file>
|
||||
<file>Icons/flags/br.png</file>
|
||||
<file>Icons/flags/bs.png</file>
|
||||
<file>Icons/flags/bt.png</file>
|
||||
<file>Icons/flags/bv.png</file>
|
||||
<file>Icons/flags/bw.png</file>
|
||||
<file>Icons/flags/by.png</file>
|
||||
<file>Icons/flags/bz.png</file>
|
||||
<file>Icons/flags/ca.png</file>
|
||||
<file>Icons/flags/cc.png</file>
|
||||
<file>Icons/flags/cd.png</file>
|
||||
<file>Icons/flags/cf.png</file>
|
||||
<file>Icons/flags/cg.png</file>
|
||||
<file>Icons/flags/ch.png</file>
|
||||
<file>Icons/flags/ci.png</file>
|
||||
<file>Icons/flags/ck.png</file>
|
||||
<file>Icons/flags/cl.png</file>
|
||||
<file>Icons/flags/cm.png</file>
|
||||
<file>Icons/flags/cn.png</file>
|
||||
<file>Icons/flags/co.png</file>
|
||||
<file>Icons/flags/cr.png</file>
|
||||
<file>Icons/flags/cs.png</file>
|
||||
<file>Icons/flags/cu.png</file>
|
||||
<file>Icons/flags/cv.png</file>
|
||||
<file>Icons/flags/cx.png</file>
|
||||
<file>Icons/flags/cy.png</file>
|
||||
<file>Icons/flags/cz.png</file>
|
||||
<file>Icons/flags/de.png</file>
|
||||
<file>Icons/flags/dj.png</file>
|
||||
<file>Icons/flags/dk.png</file>
|
||||
<file>Icons/flags/dm.png</file>
|
||||
<file>Icons/flags/do.png</file>
|
||||
<file>Icons/flags/dz.png</file>
|
||||
<file>Icons/flags/ec.png</file>
|
||||
<file>Icons/flags/ee.png</file>
|
||||
<file>Icons/flags/eg.png</file>
|
||||
<file>Icons/flags/eh.png</file>
|
||||
<file>Icons/flags/er.png</file>
|
||||
<file>Icons/flags/es.png</file>
|
||||
<file>Icons/flags/et.png</file>
|
||||
<file>Icons/flags/fi.png</file>
|
||||
<file>Icons/flags/fj.png</file>
|
||||
<file>Icons/flags/fk.png</file>
|
||||
<file>Icons/flags/fm.png</file>
|
||||
<file>Icons/flags/fo.png</file>
|
||||
<file>Icons/flags/fr.png</file>
|
||||
<file>Icons/flags/ga.png</file>
|
||||
<file>Icons/flags/gb.png</file>
|
||||
<file>Icons/flags/gd.png</file>
|
||||
<file>Icons/flags/ge.png</file>
|
||||
<file>Icons/flags/gf.png</file>
|
||||
<file>Icons/flags/gh.png</file>
|
||||
<file>Icons/flags/gi.png</file>
|
||||
<file>Icons/flags/gl.png</file>
|
||||
<file>Icons/flags/gm.png</file>
|
||||
<file>Icons/flags/gn.png</file>
|
||||
<file>Icons/flags/gp.png</file>
|
||||
<file>Icons/flags/gq.png</file>
|
||||
<file>Icons/flags/gr.png</file>
|
||||
<file>Icons/flags/gs.png</file>
|
||||
<file>Icons/flags/gt.png</file>
|
||||
<file>Icons/flags/gu.png</file>
|
||||
<file>Icons/flags/gw.png</file>
|
||||
<file>Icons/flags/gy.png</file>
|
||||
<file>Icons/flags/hk.png</file>
|
||||
<file>Icons/flags/hm.png</file>
|
||||
<file>Icons/flags/hn.png</file>
|
||||
<file>Icons/flags/hr.png</file>
|
||||
<file>Icons/flags/ht.png</file>
|
||||
<file>Icons/flags/hu.png</file>
|
||||
<file>Icons/flags/id.png</file>
|
||||
<file>Icons/flags/ie.png</file>
|
||||
<file>Icons/flags/il.png</file>
|
||||
<file>Icons/flags/in.png</file>
|
||||
<file>Icons/flags/io.png</file>
|
||||
<file>Icons/flags/iq.png</file>
|
||||
<file>Icons/flags/ir.png</file>
|
||||
<file>Icons/flags/is.png</file>
|
||||
<file>Icons/flags/it.png</file>
|
||||
<file>Icons/flags/jm.png</file>
|
||||
<file>Icons/flags/jo.png</file>
|
||||
<file>Icons/flags/jp.png</file>
|
||||
<file>Icons/flags/ke.png</file>
|
||||
<file>Icons/flags/kg.png</file>
|
||||
<file>Icons/flags/kh.png</file>
|
||||
<file>Icons/flags/ki.png</file>
|
||||
<file>Icons/flags/km.png</file>
|
||||
<file>Icons/flags/kn.png</file>
|
||||
<file>Icons/flags/kp.png</file>
|
||||
<file>Icons/flags/kr.png</file>
|
||||
<file>Icons/flags/kw.png</file>
|
||||
<file>Icons/flags/ky.png</file>
|
||||
<file>Icons/flags/kz.png</file>
|
||||
<file>Icons/flags/la.png</file>
|
||||
<file>Icons/flags/lb.png</file>
|
||||
<file>Icons/flags/lc.png</file>
|
||||
<file>Icons/flags/li.png</file>
|
||||
<file>Icons/flags/lk.png</file>
|
||||
<file>Icons/flags/lr.png</file>
|
||||
<file>Icons/flags/ls.png</file>
|
||||
<file>Icons/flags/lt.png</file>
|
||||
<file>Icons/flags/lu.png</file>
|
||||
<file>Icons/flags/lv.png</file>
|
||||
<file>Icons/flags/ly.png</file>
|
||||
<file>Icons/flags/ma.png</file>
|
||||
<file>Icons/flags/mc.png</file>
|
||||
<file>Icons/flags/md.png</file>
|
||||
<file>Icons/flags/me.png</file>
|
||||
<file>Icons/flags/mg.png</file>
|
||||
<file>Icons/flags/mh.png</file>
|
||||
<file>Icons/flags/mk.png</file>
|
||||
<file>Icons/flags/ml.png</file>
|
||||
<file>Icons/flags/mm.png</file>
|
||||
<file>Icons/flags/mn.png</file>
|
||||
<file>Icons/flags/mo.png</file>
|
||||
<file>Icons/flags/mp.png</file>
|
||||
<file>Icons/flags/mq.png</file>
|
||||
<file>Icons/flags/mr.png</file>
|
||||
<file>Icons/flags/ms.png</file>
|
||||
<file>Icons/flags/mt.png</file>
|
||||
<file>Icons/flags/mu.png</file>
|
||||
<file>Icons/flags/mv.png</file>
|
||||
<file>Icons/flags/mw.png</file>
|
||||
<file>Icons/flags/mx.png</file>
|
||||
<file>Icons/flags/my.png</file>
|
||||
<file>Icons/flags/mz.png</file>
|
||||
<file>Icons/flags/na.png</file>
|
||||
<file>Icons/flags/nc.png</file>
|
||||
<file>Icons/flags/ne.png</file>
|
||||
<file>Icons/flags/nf.png</file>
|
||||
<file>Icons/flags/ng.png</file>
|
||||
<file>Icons/flags/ni.png</file>
|
||||
<file>Icons/flags/nl.png</file>
|
||||
<file>Icons/flags/no.png</file>
|
||||
<file>Icons/flags/np.png</file>
|
||||
<file>Icons/flags/nr.png</file>
|
||||
<file>Icons/flags/nu.png</file>
|
||||
<file>Icons/flags/nz.png</file>
|
||||
<file>Icons/flags/om.png</file>
|
||||
<file>Icons/flags/pa.png</file>
|
||||
<file>Icons/flags/pe.png</file>
|
||||
<file>Icons/flags/pf.png</file>
|
||||
<file>Icons/flags/pg.png</file>
|
||||
<file>Icons/flags/ph.png</file>
|
||||
<file>Icons/flags/pk.png</file>
|
||||
<file>Icons/flags/pl.png</file>
|
||||
<file>Icons/flags/pm.png</file>
|
||||
<file>Icons/flags/pn.png</file>
|
||||
<file>Icons/flags/pr.png</file>
|
||||
<file>Icons/flags/ps.png</file>
|
||||
<file>Icons/flags/pt.png</file>
|
||||
<file>Icons/flags/pw.png</file>
|
||||
<file>Icons/flags/py.png</file>
|
||||
<file>Icons/flags/qa.png</file>
|
||||
<file>Icons/flags/re.png</file>
|
||||
<file>Icons/flags/ro.png</file>
|
||||
<file>Icons/flags/rs.png</file>
|
||||
<file>Icons/flags/ru.png</file>
|
||||
<file>Icons/flags/rw.png</file>
|
||||
<file>Icons/flags/sa.png</file>
|
||||
<file>Icons/flags/sb.png</file>
|
||||
<file>Icons/flags/sc.png</file>
|
||||
<file>Icons/flags/sd.png</file>
|
||||
<file>Icons/flags/se.png</file>
|
||||
<file>Icons/flags/sg.png</file>
|
||||
<file>Icons/flags/sh.png</file>
|
||||
<file>Icons/flags/si.png</file>
|
||||
<file>Icons/flags/sj.png</file>
|
||||
<file>Icons/flags/sk.png</file>
|
||||
<file>Icons/flags/sl.png</file>
|
||||
<file>Icons/flags/sm.png</file>
|
||||
<file>Icons/flags/sn.png</file>
|
||||
<file>Icons/flags/so.png</file>
|
||||
<file>Icons/flags/sr.png</file>
|
||||
<file>Icons/flags/st.png</file>
|
||||
<file>Icons/flags/sv.png</file>
|
||||
<file>Icons/flags/sy.png</file>
|
||||
<file>Icons/flags/sz.png</file>
|
||||
<file>Icons/flags/tc.png</file>
|
||||
<file>Icons/flags/td.png</file>
|
||||
<file>Icons/flags/tf.png</file>
|
||||
<file>Icons/flags/tg.png</file>
|
||||
<file>Icons/flags/th.png</file>
|
||||
<file>Icons/flags/tj.png</file>
|
||||
<file>Icons/flags/tk.png</file>
|
||||
<file>Icons/flags/tl.png</file>
|
||||
<file>Icons/flags/tm.png</file>
|
||||
<file>Icons/flags/tn.png</file>
|
||||
<file>Icons/flags/to.png</file>
|
||||
<file>Icons/flags/tr.png</file>
|
||||
<file>Icons/flags/tt.png</file>
|
||||
<file>Icons/flags/tv.png</file>
|
||||
<file>Icons/flags/tw.png</file>
|
||||
<file>Icons/flags/tz.png</file>
|
||||
<file>Icons/flags/ua.png</file>
|
||||
<file>Icons/flags/ug.png</file>
|
||||
<file>Icons/flags/um.png</file>
|
||||
<file>Icons/flags/us.png</file>
|
||||
<file>Icons/flags/uy.png</file>
|
||||
<file>Icons/flags/uz.png</file>
|
||||
<file>Icons/flags/va.png</file>
|
||||
<file>Icons/flags/vc.png</file>
|
||||
<file>Icons/flags/ve.png</file>
|
||||
<file>Icons/flags/vg.png</file>
|
||||
<file>Icons/flags/vi.png</file>
|
||||
<file>Icons/flags/vn.png</file>
|
||||
<file>Icons/flags/vu.png</file>
|
||||
<file>Icons/flags/wf.png</file>
|
||||
<file>Icons/flags/ws.png</file>
|
||||
<file>Icons/flags/ye.png</file>
|
||||
<file>Icons/flags/yt.png</file>
|
||||
<file>Icons/flags/za.png</file>
|
||||
<file>Icons/flags/zm.png</file>
|
||||
<file>Icons/flags/zw.png</file>
|
||||
<file>Icons/oxygen/application-exit.png</file>
|
||||
<file>Icons/oxygen/application-rss+xml.png</file>
|
||||
<file>Icons/oxygen/application-x-mswinurl.png</file>
|
||||
<file>Icons/oxygen/chronometer.png</file>
|
||||
<file>Icons/oxygen/dialog-cancel.png</file>
|
||||
<file>Icons/oxygen/dialog-information.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/document-edit-verify.png</file>
|
||||
<file>Icons/oxygen/document-edit.png</file>
|
||||
<file>Icons/oxygen/document-encrypt.png</file>
|
||||
<file>Icons/oxygen/document-import.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/document-properties.png</file>
|
||||
<file>Icons/oxygen/document-save.png</file>
|
||||
<file>Icons/oxygen/download.png</file>
|
||||
<file>Icons/oxygen/edit-clear-history.png</file>
|
||||
<file>Icons/oxygen/edit-clear.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/edit-delete.png</file>
|
||||
<file>Icons/oxygen/edit-find-user.png</file>
|
||||
<file>Icons/oxygen/edit-find.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/edit-rename.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/folder-new.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/go-down.png</file>
|
||||
<file>Icons/oxygen/go-up.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/help-contents.png</file>
|
||||
<file>Icons/oxygen/inode-directory.png</file>
|
||||
<file>Icons/oxygen/insert-link.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/mail-mark-read.png</file>
|
||||
<file>Icons/oxygen/media-playback-pause.png</file>
|
||||
<file>Icons/oxygen/media-playback-start.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/network-wired.png</file>
|
||||
<file>Icons/oxygen/object-locked.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/preferences-other.png</file>
|
||||
<file>Icons/oxygen/preferences-system-network.png</file>
|
||||
<file>Icons/oxygen/preferences-system.png</file>
|
||||
<file>Icons/oxygen/preferences-web-browser-cookies.png</file>
|
||||
<file>Icons/oxygen/security-high.png</file>
|
||||
<file>Icons/oxygen/security-low.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/task-attention.png</file>
|
||||
<file>Icons/oxygen/text-plain.png</file>
|
||||
<file>Icons/oxygen/tools-report-bug.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/view-calendar-journal.png</file>
|
||||
<file>Icons/oxygen/view-categories.png</file>
|
||||
<file>Icons/oxygen/view-filter.png</file>
|
||||
<file>Icons/oxygen/view-preview.png</file>
|
||||
<file>Icons/oxygen/view-refresh.png</file>
|
||||
<file>Icons/oxygen/view-statistics.png</file>
|
||||
<file>Icons/oxygen/wallet-open.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/skin/arrow-right.gif</file>
|
||||
<file>Icons/skin/bg-handle-horizontal.gif</file>
|
||||
<file>Icons/skin/checking.png</file>
|
||||
<file>Icons/L.gif</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/connected.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/disconnected.png</file>
|
||||
<file>Icons/skin/download.png</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/error.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/mascot.png</file>
|
||||
<file>Icons/skin/paused.png</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/qbittorrent_mono_dark.png</file>
|
||||
<file>Icons/skin/qbittorrent_mono_light.png</file>
|
||||
<file>Icons/skin/queued.png</file>
|
||||
<file>Icons/skin/ratio.png</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/slider-area.gif</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/stalledDL.png</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/error.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/skin/uploading.png</file>
|
||||
<file>Icons/skin/queued.png</file>
|
||||
<file>Icons/skin/checking.png</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/arrow-right.gif</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/skin/bg-handle-horizontal.gif</file>
|
||||
<file>Icons/skin/download.png</file>
|
||||
<file>Icons/flags/sm.png</file>
|
||||
<file>Icons/flags/lt.png</file>
|
||||
<file>Icons/flags/th.png</file>
|
||||
<file>Icons/flags/sd.png</file>
|
||||
<file>Icons/flags/mr.png</file>
|
||||
<file>Icons/flags/by.png</file>
|
||||
<file>Icons/flags/sc.png</file>
|
||||
<file>Icons/flags/mz.png</file>
|
||||
<file>Icons/flags/tt.png</file>
|
||||
<file>Icons/flags/kp.png</file>
|
||||
<file>Icons/flags/re.png</file>
|
||||
<file>Icons/flags/um.png</file>
|
||||
<file>Icons/flags/ec.png</file>
|
||||
<file>Icons/flags/fk.png</file>
|
||||
<file>Icons/flags/aw.png</file>
|
||||
<file>Icons/flags/lb.png</file>
|
||||
<file>Icons/flags/vg.png</file>
|
||||
<file>Icons/flags/do.png</file>
|
||||
<file>Icons/flags/ee.png</file>
|
||||
<file>Icons/flags/ck.png</file>
|
||||
<file>Icons/flags/gn.png</file>
|
||||
<file>Icons/flags/cg.png</file>
|
||||
<file>Icons/flags/ao.png</file>
|
||||
<file>Icons/flags/dk.png</file>
|
||||
<file>Icons/flags/ms.png</file>
|
||||
<file>Icons/flags/sg.png</file>
|
||||
<file>Icons/flags/bw.png</file>
|
||||
<file>Icons/flags/br.png</file>
|
||||
<file>Icons/flags/cn.png</file>
|
||||
<file>Icons/flags/ua.png</file>
|
||||
<file>Icons/flags/ae.png</file>
|
||||
<file>Icons/flags/tg.png</file>
|
||||
<file>Icons/flags/ge.png</file>
|
||||
<file>Icons/flags/ne.png</file>
|
||||
<file>Icons/flags/km.png</file>
|
||||
<file>Icons/flags/bf.png</file>
|
||||
<file>Icons/flags/nf.png</file>
|
||||
<file>Icons/flags/az.png</file>
|
||||
<file>Icons/flags/sl.png</file>
|
||||
<file>Icons/flags/md.png</file>
|
||||
<file>Icons/flags/ph.png</file>
|
||||
<file>Icons/flags/mc.png</file>
|
||||
<file>Icons/flags/mq.png</file>
|
||||
<file>Icons/flags/ng.png</file>
|
||||
<file>Icons/flags/vu.png</file>
|
||||
<file>Icons/flags/et.png</file>
|
||||
<file>Icons/flags/bj.png</file>
|
||||
<file>Icons/flags/nl.png</file>
|
||||
<file>Icons/flags/ad.png</file>
|
||||
<file>Icons/flags/tv.png</file>
|
||||
<file>Icons/flags/fj.png</file>
|
||||
<file>Icons/flags/to.png</file>
|
||||
<file>Icons/flags/ru.png</file>
|
||||
<file>Icons/flags/jp.png</file>
|
||||
<file>Icons/flags/ma.png</file>
|
||||
<file>Icons/flags/bz.png</file>
|
||||
<file>Icons/flags/vn.png</file>
|
||||
<file>Icons/flags/bt.png</file>
|
||||
<file>Icons/flags/ht.png</file>
|
||||
<file>Icons/flags/kw.png</file>
|
||||
<file>Icons/flags/tr.png</file>
|
||||
<file>Icons/flags/sy.png</file>
|
||||
<file>Icons/flags/nr.png</file>
|
||||
<file>Icons/flags/nz.png</file>
|
||||
<file>Icons/flags/np.png</file>
|
||||
<file>Icons/flags/uz.png</file>
|
||||
<file>Icons/flags/in.png</file>
|
||||
<file>Icons/flags/ga.png</file>
|
||||
<file>Icons/flags/sa.png</file>
|
||||
<file>Icons/flags/tl.png</file>
|
||||
<file>Icons/flags/ly.png</file>
|
||||
<file>Icons/flags/lr.png</file>
|
||||
<file>Icons/flags/cz.png</file>
|
||||
<file>Icons/flags/bm.png</file>
|
||||
<file>Icons/flags/us.png</file>
|
||||
<file>Icons/flags/ye.png</file>
|
||||
<file>Icons/flags/gs.png</file>
|
||||
<file>Icons/flags/sb.png</file>
|
||||
<file>Icons/flags/hm.png</file>
|
||||
<file>Icons/flags/ke.png</file>
|
||||
<file>Icons/flags/so.png</file>
|
||||
<file>Icons/flags/ni.png</file>
|
||||
<file>Icons/flags/cm.png</file>
|
||||
<file>Icons/flags/li.png</file>
|
||||
<file>Icons/flags/gp.png</file>
|
||||
<file>Icons/flags/co.png</file>
|
||||
<file>Icons/flags/kz.png</file>
|
||||
<file>Icons/flags/de.png</file>
|
||||
<file>Icons/flags/mm.png</file>
|
||||
<file>Icons/flags/gb.png</file>
|
||||
<file>Icons/flags/mx.png</file>
|
||||
<file>Icons/flags/la.png</file>
|
||||
<file>Icons/flags/au.png</file>
|
||||
<file>Icons/flags/gu.png</file>
|
||||
<file>Icons/flags/gw.png</file>
|
||||
<file>Icons/flags/lc.png</file>
|
||||
<file>Icons/flags/st.png</file>
|
||||
<file>Icons/flags/nc.png</file>
|
||||
<file>Icons/flags/ch.png</file>
|
||||
<file>Icons/flags/cd.png</file>
|
||||
<file>Icons/flags/mh.png</file>
|
||||
<file>Icons/flags/pg.png</file>
|
||||
<file>Icons/flags/bh.png</file>
|
||||
<file>Icons/flags/kr.png</file>
|
||||
<file>Icons/flags/is.png</file>
|
||||
<file>Icons/flags/gh.png</file>
|
||||
<file>Icons/flags/mp.png</file>
|
||||
<file>Icons/flags/ca.png</file>
|
||||
<file>Icons/flags/bi.png</file>
|
||||
<file>Icons/flags/yt.png</file>
|
||||
<file>Icons/flags/it.png</file>
|
||||
<file>Icons/flags/kn.png</file>
|
||||
<file>Icons/flags/ve.png</file>
|
||||
<file>Icons/flags/cu.png</file>
|
||||
<file>Icons/flags/bs.png</file>
|
||||
<file>Icons/flags/rs.png</file>
|
||||
<file>Icons/flags/tw.png</file>
|
||||
<file>Icons/flags/bd.png</file>
|
||||
<file>Icons/flags/pr.png</file>
|
||||
<file>Icons/flags/lk.png</file>
|
||||
<file>Icons/flags/sn.png</file>
|
||||
<file>Icons/flags/gr.png</file>
|
||||
<file>Icons/flags/gm.png</file>
|
||||
<file>Icons/flags/na.png</file>
|
||||
<file>Icons/flags/om.png</file>
|
||||
<file>Icons/flags/tz.png</file>
|
||||
<file>Icons/flags/as.png</file>
|
||||
<file>Icons/flags/no.png</file>
|
||||
<file>Icons/flags/mv.png</file>
|
||||
<file>Icons/flags/ki.png</file>
|
||||
<file>Icons/flags/eg.png</file>
|
||||
<file>Icons/flags/tj.png</file>
|
||||
<file>Icons/flags/sj.png</file>
|
||||
<file>Icons/flags/fi.png</file>
|
||||
<file>Icons/flags/lv.png</file>
|
||||
<file>Icons/flags/cx.png</file>
|
||||
<file>Icons/flags/ci.png</file>
|
||||
<file>Icons/flags/vi.png</file>
|
||||
<file>Icons/flags/be.png</file>
|
||||
<file>Icons/flags/mw.png</file>
|
||||
<file>Icons/flags/zw.png</file>
|
||||
<file>Icons/flags/si.png</file>
|
||||
<file>Icons/flags/dm.png</file>
|
||||
<file>Icons/flags/jo.png</file>
|
||||
<file>Icons/flags/hk.png</file>
|
||||
<file>Icons/flags/me.png</file>
|
||||
<file>Icons/flags/va.png</file>
|
||||
<file>Icons/flags/pm.png</file>
|
||||
<file>Icons/flags/qa.png</file>
|
||||
<file>Icons/flags/cc.png</file>
|
||||
<file>Icons/flags/kh.png</file>
|
||||
<file>Icons/flags/id.png</file>
|
||||
<file>Icons/flags/ai.png</file>
|
||||
<file>Icons/flags/mn.png</file>
|
||||
<file>Icons/flags/gd.png</file>
|
||||
<file>Icons/flags/mt.png</file>
|
||||
<file>Icons/flags/gq.png</file>
|
||||
<file>Icons/flags/hr.png</file>
|
||||
<file>Icons/flags/sv.png</file>
|
||||
<file>Icons/flags/dz.png</file>
|
||||
<file>Icons/flags/kg.png</file>
|
||||
<file>Icons/flags/gy.png</file>
|
||||
<file>Icons/flags/bv.png</file>
|
||||
<file>Icons/flags/ag.png</file>
|
||||
<file>Icons/flags/hn.png</file>
|
||||
<file>Icons/flags/ml.png</file>
|
||||
<file>Icons/flags/fo.png</file>
|
||||
<file>Icons/flags/pw.png</file>
|
||||
<file>Icons/flags/mg.png</file>
|
||||
<file>Icons/flags/iq.png</file>
|
||||
<file>Icons/flags/jm.png</file>
|
||||
<file>Icons/flags/bo.png</file>
|
||||
<file>Icons/flags/sk.png</file>
|
||||
<file>Icons/flags/sh.png</file>
|
||||
<file>Icons/flags/tf.png</file>
|
||||
<file>Icons/flags/mk.png</file>
|
||||
<file>Icons/flags/my.png</file>
|
||||
<file>Icons/flags/es.png</file>
|
||||
<file>Icons/flags/py.png</file>
|
||||
<file>Icons/flags/ax.png</file>
|
||||
<file>Icons/flags/ls.png</file>
|
||||
<file>Icons/flags/tn.png</file>
|
||||
<file>Icons/flags/ps.png</file>
|
||||
<file>Icons/flags/bn.png</file>
|
||||
<file>Icons/flags/dj.png</file>
|
||||
<file>Icons/flags/cs.png</file>
|
||||
<file>Icons/flags/pl.png</file>
|
||||
<file>Icons/flags/cl.png</file>
|
||||
<file>Icons/flags/pf.png</file>
|
||||
<file>Icons/flags/gi.png</file>
|
||||
<file>Icons/flags/bb.png</file>
|
||||
<file>Icons/flags/ws.png</file>
|
||||
<file>Icons/flags/cy.png</file>
|
||||
<file>Icons/flags/pt.png</file>
|
||||
<file>Icons/flags/ba.png</file>
|
||||
<file>Icons/flags/gl.png</file>
|
||||
<file>Icons/flags/ie.png</file>
|
||||
<file>Icons/flags/fr.png</file>
|
||||
<file>Icons/flags/tm.png</file>
|
||||
<file>Icons/flags/er.png</file>
|
||||
<file>Icons/flags/cr.png</file>
|
||||
<file>Icons/flags/af.png</file>
|
||||
<file>Icons/flags/mu.png</file>
|
||||
<file>Icons/flags/lu.png</file>
|
||||
<file>Icons/flags/pk.png</file>
|
||||
<file>Icons/flags/am.png</file>
|
||||
<file>Icons/flags/ar.png</file>
|
||||
<file>Icons/flags/uy.png</file>
|
||||
<file>Icons/flags/hu.png</file>
|
||||
<file>Icons/flags/pn.png</file>
|
||||
<file>Icons/flags/gf.png</file>
|
||||
<file>Icons/flags/ir.png</file>
|
||||
<file>Icons/flags/pe.png</file>
|
||||
<file>Icons/flags/nu.png</file>
|
||||
<file>Icons/flags/ro.png</file>
|
||||
<file>Icons/flags/mo.png</file>
|
||||
<file>Icons/flags/za.png</file>
|
||||
<file>Icons/flags/ky.png</file>
|
||||
<file>Icons/flags/zm.png</file>
|
||||
<file>Icons/flags/se.png</file>
|
||||
<file>Icons/flags/il.png</file>
|
||||
<file>Icons/flags/fm.png</file>
|
||||
<file>Icons/flags/sr.png</file>
|
||||
<file>Icons/flags/pa.png</file>
|
||||
<file>Icons/flags/cv.png</file>
|
||||
<file>Icons/flags/tc.png</file>
|
||||
<file>Icons/flags/an.png</file>
|
||||
<file>Icons/flags/sz.png</file>
|
||||
<file>Icons/flags/io.png</file>
|
||||
<file>Icons/flags/rw.png</file>
|
||||
<file>Icons/flags/eh.png</file>
|
||||
<file>Icons/flags/cf.png</file>
|
||||
<file>Icons/flags/gt.png</file>
|
||||
<file>Icons/flags/al.png</file>
|
||||
<file>Icons/flags/ug.png</file>
|
||||
<file>Icons/flags/td.png</file>
|
||||
<file>Icons/flags/at.png</file>
|
||||
<file>Icons/flags/vc.png</file>
|
||||
<file>Icons/flags/tk.png</file>
|
||||
<file>Icons/flags/bg.png</file>
|
||||
<file>Icons/flags/wf.png</file>
|
||||
<file>Icons/oxygen/preferences-system.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/document-edit-verify.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/edit-clear-history.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/document-edit.png</file>
|
||||
<file>Icons/oxygen/insert-link.png</file>
|
||||
<file>Icons/oxygen/network-wired.png</file>
|
||||
<file>Icons/oxygen/mail-mark-read.png</file>
|
||||
<file>Icons/oxygen/go-up.png</file>
|
||||
<file>Icons/oxygen/application-exit.png</file>
|
||||
<file>Icons/oxygen/edit-rename.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/media-playback-start.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/edit-find-user.png</file>
|
||||
<file>Icons/oxygen/media-playback-pause.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/inode-directory.png</file>
|
||||
<file>Icons/oxygen/tools-report-bug.png</file>
|
||||
<file>Icons/oxygen/view-filter.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/oxygen/view-preview.png</file>
|
||||
<file>Icons/oxygen/view-refresh.png</file>
|
||||
<file>Icons/oxygen/text-plain.png</file>
|
||||
<file>Icons/oxygen/edit-delete.png</file>
|
||||
<file>Icons/oxygen/chronometer.png</file>
|
||||
<file>Icons/oxygen/dialog-cancel.png</file>
|
||||
<file>Icons/oxygen/preferences-system-network.png</file>
|
||||
<file>Icons/oxygen/document-properties.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/wallet-open.png</file>
|
||||
<file>Icons/oxygen/preferences-web-browser-cookies.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/document-save.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/view-categories.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/dialog-information.png</file>
|
||||
<file>Icons/oxygen/preferences-other.png</file>
|
||||
<file>Icons/oxygen/object-locked.png</file>
|
||||
<file>Icons/oxygen/view-calendar-journal.png</file>
|
||||
<file>Icons/oxygen/application-rss+xml.png</file>
|
||||
<file>Icons/oxygen/document-encrypt.png</file>
|
||||
<file>Icons/oxygen/help-contents.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/application-x-mswinurl.png</file>
|
||||
<file>Icons/oxygen/go-down.png</file>
|
||||
<file>Icons/oxygen/document-import.png</file>
|
||||
<file>Icons/oxygen/download.png</file>
|
||||
<file>Icons/oxygen/edit-find.png</file>
|
||||
<file>Icons/oxygen/edit-clear.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/oxygen/folder-new.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
67
src/lang.qrc
@@ -1,44 +1,37 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>lang/qbittorrent_ar.qm</file>
|
||||
<file>lang/qbittorrent_be.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_en_AU.qm</file>
|
||||
<file>lang/qbittorrent_en_GB.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_eu.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_gl.qm</file>
|
||||
<file>lang/qbittorrent_he.qm</file>
|
||||
<file>lang/qbittorrent_hr.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_hy.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_ka.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_lt.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_ru.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_sr.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_vi.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_zh_TW.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_lt.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_gl.qm</file>
|
||||
<file>lang/qbittorrent_sr.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_hy.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ar.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_hr.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,42 +0,0 @@
|
||||
For future maintainers on how to update translations from Transifex.
|
||||
|
||||
Project page: https://www.transifex.com/projects/p/qbittorrent/
|
||||
|
||||
Most of the options are setup in the .tx/config file. You will need to have the Transifex client app in your path.
|
||||
The examples use the tx app on Windows. Other OSs should be similar.
|
||||
|
||||
===Updating the translations===
|
||||
1. In the root folder of the project just run "tx pull"
|
||||
2. Commit to git
|
||||
|
||||
===Pulling new translation files===
|
||||
1. In the root folder of the project just run "tx pull -a"
|
||||
2. Commit to git each translation file separately with its own message.
|
||||
3. After you commit all new files expose them in app. Edit:
|
||||
a. lang.qrc
|
||||
b. options_imp.cpp: options_imp::languageToLocalizedString()
|
||||
c. src.pro: The TRANSLATIONS var
|
||||
d. preferences_content.html: search for: <select id="locale_select">
|
||||
|
||||
Note: This will also pull updated translations if you haven't already 'tx pull'.
|
||||
|
||||
===Updating the qBittorrent.desktop file===
|
||||
1. In the root folder of the project just run "tx pull -s -r qbittorrent.qbittorrentdesktop_master"
|
||||
2. Commit to git
|
||||
|
||||
It will pull the source file (en). However, in this case .desktop files contain all other translations
|
||||
when you pull the source file.
|
||||
|
||||
===When making new branch===
|
||||
1. Switch to new branch
|
||||
2. Edit the .tx.config file. You should change the resource for the qbt translations from 'qbittorrent.qbittorrent_master'
|
||||
to eg 'qbittorrent.qbittorrent_v3_1_x'. It follows this spec: <project>.<resource_slug>_<branchname>'
|
||||
3. Commit to git
|
||||
4. Use this command to create the new resource on the server and push the translations files "tx push -s -t"
|
||||
|
||||
===Updating the source file==
|
||||
When you run lupdate Transifex needs to know that the source is updated. When creating a new resource on transifex
|
||||
you should go to the website, select the resource and hit "edit resource". From there you should update the
|
||||
"Source file URL". It should point to the exact file in the github repository(eg src/lang/qbittorrent_en.ts). Be sure to copy
|
||||
the 'raw' link presented by github and not the regular one. This will make Transifex fetch automatically the source file
|
||||
from the repo(maybe once a day). If you want to instantly update the resouce then on the correct branch run "tx push -s"
|
||||
BIN
src/lang/qbittorrent_ar.qm
Normal file
BIN
src/lang/qbittorrent_bg.qm
Normal file
BIN
src/lang/qbittorrent_ca.qm
Normal file
BIN
src/lang/qbittorrent_cs.qm
Normal file
BIN
src/lang/qbittorrent_da.qm
Normal file
BIN
src/lang/qbittorrent_de.qm
Normal file
BIN
src/lang/qbittorrent_el.qm
Normal file
1
src/lang/qbittorrent_en.qm
Normal file
@@ -0,0 +1 @@
|
||||
<クdハ<>箆!ソ`。スン
|
||||