Compare commits

..

10 Commits

Author SHA1 Message Date
Christophe Dumez
673ca8db84 Tagged v2.6.1 release 2011-01-10 18:18:38 +00:00
Christophe Dumez
bbd9764f9c Reduced top toolbar spacing 2011-01-10 17:55:27 +00:00
Christophe Dumez
7437bd4265 Bump to v2.6.1 2011-01-10 17:39:47 +00:00
Christophe Dumez
1299e75934 BUGFIX: Fix magnet torrent name update problem 2011-01-10 17:36:17 +00:00
Christophe Dumez
514f82a3c9 Move transfer list filter on the right side of the toolbar 2011-01-10 17:12:55 +00:00
Christophe Dumez
51a69dc36a Also fix toolbar icon size in Web UI 2011-01-10 16:57:57 +00:00
Christophe Dumez
737fee79ed COSMETIC: Use 24px size for toolbar icons 2011-01-10 15:54:20 +00:00
Christophe Dumez
e5e4bb1111 BUGFIX: Fix some missing icons in the Web UI 2011-01-09 19:41:11 +00:00
Christophe Dumez
75111cdd8a BUGFIX: Really disable torrent addition dialog by default 2011-01-09 14:02:28 +00:00
Christophe Dumez
f5f915eb5d Branched v2.6.x series 2011-01-09 11:08:51 +00:00
526 changed files with 106502 additions and 188414 deletions

15
.gitignore vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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

57
AUTHORS
View File

@@ -1,11 +1,7 @@
Current maintainer:
* Sledgehammer999 <sledgehammer999@qbittorrent.org>
Original author:
Author:
* Christophe Dumez <chris@qbittorrent.org>
Contributors:
* Vladimir Golovnev <glassez@yandex.ru>
* Stefanos Antaris <santaris@csd.auth.gr>
* Mohammad Dib <mdib@qbittorrent.org>
* Mirco Chinelli <infinity89@fastwebmail.it>
@@ -14,7 +10,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 +24,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 +49,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 +66,36 @@ 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)
- Armenian: Hrant Ohanyan (hrantohanyan@mail.am)
- Basque: Xabier Aramendi (azpidatziak@gmail.com)
- Belarusian: Mihas Varantsou (meequz@gmail.com)
- Arabic: SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@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
- Norwegian: Lars-Erik Labori (hamil@users.sourceforge.net)
- 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
View File

@@ -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

312
Changelog
View File

@@ -1,309 +1,9 @@
* Wed Feb 22 2015 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.12
- OSX: Fix build to work with older machines. (sledgehammer999, Noctem)
- WINDOWS: Fix automatic Python download. (sledgehammer999)
- WINDOWS: Fix crashes due to memory corruption and improve Python registry searching. (glassez)
* Wed Oct 22 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.11
- FEATURE: Allow relative torrent paths when qBittorrent is already running (pmzqla)
- FEATURE: Make Windows icons suitable for high dpi screens (pmzqla)
- FEATURE: Increase maximum size of system icons (pmzqla)
- BUGFIX: Fix crash in the "Content" widget when user would right click in it without a torrent selected (Ivan Sorokin)
- BUGFIX: Don't show multiple unlock UI dialogs. Closes #2040. (sledgehammer999)
- SEARCH: Fix bug where python would falsely be detected and nothing worked (paolo-sz)
- SEARCH: Fix TorrentReactor search plugin (Bruno Barbieri)
- SEARCH: Fix search engine encoding issues with python3 on Windows (Bruno Barbieri)
- SEARCH: Pirate bay search engine update (DoumanAsh)
- SEARCH: Internal improvements in the python code (Bruno Barbieri)
- WINDOWS: Fix magnet link association. Closes #1952. (sledgehammer999)
- WINDOWS and OSX: Fix again the program updater. The url was changed by sourceforge.net. Closes #1954. (sledgehammer999)
- OSX: Fix compilation (sledgehammer999)
- WEBUI: Set correct HTTP Content-Type in case of forbidden access. (pmzqla)
- COSMETIC: Remove unneeded tooltip (pmzqla)
- COSMETIC: Don't stretch the last section in the transfer list (pmzqla)
- COSMETIC: Set minimum width of the left panel in the preferences (pmzqla)
- OTHER: Optimize sorting of rows. This should have less CPU impact when many torrents are present. (Ivan Sorokin)
- OTHER: Use the correct character encoding for exceptions coming from libtorrent. (sledgehammer999)
- OTHER: Use boost:bind() as the docs show. Allows compilation with older gcc versions. (sledgehammer999)
* 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)
* Tue Apr 29 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.9.2
- OTHER: The v3.1.9.1 Windows build was broken
* 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 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)
* Sun Feb 02 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.8
- BUGFIX: Really fix build of v3.1.6
* Sun Feb 02 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.7
- BUGFIX: Fix build of v3.1.6
* 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.
* 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.
* 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
View File

@@ -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-thread, 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-thread, 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.

View File

@@ -1,11 +1,10 @@
qBittorrent - A BitTorrent client in Qt
qBittorrent - A BitTorrent client in Qt4
------------------------------------------
[![Build Status](https://travis-ci.org/qbittorrent/qBittorrent.png?branch=v3_1_x)](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>

View File

@@ -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:

265
configure vendored
View File

@@ -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,51 +344,9 @@ 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");
conf->addExtra("MANPREFIX = \$\$PREFIX");
#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 +377,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 +403,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 +432,147 @@ 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;
}
if(!conf->checkHeader(s, "boost/thread.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;
}
if(!conf->checkHeader(s, "boost/thread.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" << "thread";
}
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

View File

@@ -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

View File

@@ -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

View File

@@ -2,65 +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 (homebrew and macports)
INCLUDEPATH += /usr/local/include /opt/local/include /usr/include
LIBS += -L/usr/local/lib -L/opt/local/lib -L/usr/lib
# 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
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
qt_translations.path = Contents/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.")

View File

@@ -1,3 +1,5 @@
INCLUDEPATH += $$PWD
exists(conf.pri) {
# to the conf.pri goes all system dependent stuff
include(conf.pri)
@@ -7,13 +9,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.")

View File

@@ -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

View File

@@ -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'>

View File

@@ -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,84 @@ 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;
}
if(!conf->checkHeader(s, "boost/thread.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;
}
if(!conf->checkHeader(s, "boost/thread.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" << "thread";
}
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;
}
};

View File

@@ -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;
}
};

View File

@@ -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;
}
};

View File

@@ -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;
}
};

View File

@@ -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,18 +19,8 @@ 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");
conf->addExtra("MANPREFIX = $$PREFIX");
#else
conf->addExtra("MANPREFIX = $$PREFIX/share");
#endif
return(QT_VERSION >= 0x040600);
return(QT_VERSION >= 0x040500);
}
};

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,121 +1,38 @@
[Desktop Entry]
Categories=Network;FileTransfer;P2P;Qt;
Exec=qbittorrent %U
GenericName=BitTorrent client
Comment=Download and share files over BitTorrent
Categories=Qt;Network;P2P;
Comment=V2.6.1
Exec=qbittorrent %f
GenericName=Bittorrent client
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[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;
MimeType=application/x-bittorrent;
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 B

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
src/Icons/uparrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

View File

@@ -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.12</string>
<key>CFBundleGetInfoString</key>
<string>2.6.1</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-2015 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>

View File

@@ -51,7 +51,7 @@
</sizepolicy>
</property>
<property name="text">
<string notr="true">&lt;h3&gt;&lt;b&gt;qBittorrent&lt;/b&gt;&lt;/h3&gt;</string>
<string>&lt;h3&gt;&lt;b&gt;qBittorrent&lt;/b&gt;&lt;/h3&gt;</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>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt;A Bittorrent client programmed in C++, based on Qt4 toolkit &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt;and libtorrent-rasterbar. &lt;br /&gt;&lt;br /&gt;Copyright ©2006-2010 Christophe Dumez&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'DejaVu Sans'; text-decoration: underline;&quot;&gt;Home Page:&lt;/span&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt; &lt;/span&gt;&lt;a href=&quot;http://www.qbittorrent.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.qbittorrent.org&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'DejaVu Sans'; text-decoration: underline;&quot;&gt;Forum:&lt;/span&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt; &lt;/span&gt;&lt;a href=&quot;http://forum.qbittorrent.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://forum.qbittorrent.org&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'DejaVu Sans'; text-decoration: underline;&quot;&gt;IRC:&lt;/span&gt;&lt;span style=&quot; font-family:'DejaVu Sans';&quot;&gt; #qbittorrent on Freenode&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>

View File

@@ -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,44 @@ 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>\
<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>\
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@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>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)</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();
}
};

View File

@@ -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(misc::toQStringU(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 &current_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 &current_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();
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}
};

View File

@@ -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">

View File

@@ -32,211 +32,159 @@
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include "downloadthread.h"
#include "preferences.h"
#ifndef DISABLE_GUI
#include "rsssettings.h"
#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()));
reply->deleteLater();
return;
}
// Check if the server ask us to redirect somewhere lese
const QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
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();
} else {
QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(redirection.isValid()) {
// We should redirect
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(redirection.toUrl().toString()));
m_redirectMapping.insert(redirection.toUrl().toString(), url);
downloadUrl(redirection.toUrl().toString());
return;
}
m_redirectMapping.insert(newUrlString, url);
// redirecting with first cookies
downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url));
reply->deleteLater();
return;
}
// Checking if it was redirected, restoring initial URL
if (m_redirectMapping.contains(url)) {
url = m_redirectMapping.take(url);
}
// Success
QTemporaryFile *tmpfile = new QTemporaryFile;
if (tmpfile->open()) {
// Checking if it was redirecting, restoring initial URL
if(m_redirectMapping.contains(url)) {
url = m_redirectMapping.take(url);
}
// Success
QString filePath;
QTemporaryFile *tmpfile = new QTemporaryFile;
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());
if (tmpfile->open()) {
filePath = tmpfile->fileName();
qDebug("Temporary filename is: %s", qPrintable(filePath));
if(reply->open(QIODevice::ReadOnly)) {
// TODO: Support GZIP compression
tmpfile->write(reply->readAll());
reply->close();
tmpfile->close();
delete tmpfile;
// Send finished signal
emit downloadFinished(url, filePath);
} else {
// Error when reading the request
tmpfile->close();
delete tmpfile;
emit downloadFailure(url, tr("I/O Error"));
}
tmpfile->write(replyData);
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.
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"));
}
} else {
delete tmpfile;
emit downloadFailure(url, tr("I/O Error"));
}
// Clean up
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(QString url) {
#ifndef DISABLE_GUI
// Load cookies
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
if(!host_name.isEmpty())
loadCookies(host_name, url);
#endif
// 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(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.toLocal8Bit()).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());
const QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
QNetworkRequest request(qurl);
// Spoof Firefox 3.5 user agent to avoid
// Web server banning
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) {
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if (!reply) return;
if (bytesTotal > 0) {
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
if(bytesTotal > 0) {
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
// 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...
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
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,QList<QSslError> errors) {
Q_UNUSED(errors)
// Ignore all SSL errors
reply->ignoreSslErrors();

View File

@@ -32,41 +32,38 @@
#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(QString url);
void downloadTorrentUrl(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);
void downloadFinished(QString url, QString file_path);
void downloadFailure(QString url, QString reason);
private slots:
void processDlFinished(QNetworkReply* reply);
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
#ifndef QT_NO_OPENSSL
void ignoreSslErrors(QNetworkReply*,const QList<QSslError>&);
void ignoreSslErrors(QNetworkReply*,QList<QSslError>);
#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;

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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>

View File

@@ -12,7 +12,7 @@
#include <QSet>
#include <iostream>
#include <errno.h>
#if defined(Q_WS_MAC) || defined(Q_OS_FREEBSD)
#ifdef Q_WS_MAC
#include <sys/param.h>
#include <sys/mount.h>
#include <string.h>
@@ -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();
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,57 +57,28 @@ void IconProvider::drop()
QIcon IconProvider::getIcon(const QString &iconId)
{
#if defined(Q_WS_X11)
if (m_useSystemTheme) {
QIcon icon = QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
icon = generateDifferentSizes(icon);
return icon;
}
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
if(m_useSystemTheme)
return QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
#endif
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 new_icon;
QList<QSize> required_sizes;
required_sizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32);
QList<QIcon::Mode> modes;
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
foreach (const QSize& size, required_sizes) {
foreach (QIcon::Mode mode, modes) {
QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off);
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())
pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
new_icon.addPixmap(pixon, mode, QIcon::On);
}
}
return new_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);
}

View File

@@ -46,15 +46,12 @@ 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);
private:
QIcon generateDifferentSizes(const QIcon& icon);
private:
bool m_useSystemTheme;
#endif

View File

@@ -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>

View File

@@ -1,44 +1,35 @@
<!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_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_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>

View File

@@ -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

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_bg.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_ca.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_cs.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_da.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_de.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_el.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
<クd<>箆!ソ`。スン

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_es.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
src/lang/qbittorrent_fi.qm Normal file

Binary file not shown.

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